void HDR::gsolve(std::vector<std::vector<uchar>>& z, std::vector<float>& g, std::vector<float>& lE) { if (z.size() != P || z[0].size() != N) { std::stringstream ss; ss << "Error in HDR::gsolve(): input matrix must be (NxP).\n\tz is of size " << z.size() << " but P=" << P << "\n\tz[0] is of size " << z[0].size() << " but N=" << N; throw std::exception(ss.str().c_str()); } int n = 256; //lapack_int nlines = N*P+n+1, ncols = n+N; int nlins = N*P+n+1, ncols = n+N; double* b = new double[nlins]; double** A = new double*[nlins]; for (int k=0; k<nlins; k++) { b[k] = 0; A[k] = new double[ncols]; for (int l=0; l<ncols; l++) { A[k][l] = 0; } } // Include the data-fitting equations int k = 0; // For all pixel locations for (int i=0; i<N; i++) { // For all images for (int j=0; j<P; j++) { int wij = weight(z[j][i] + 1); A[k][z[j][i]+1] = wij; A[k][n+i] = -wij; b[k] = wij * B[j]; k++; } } // Fix the curve by setting its middle value to 0 A[k][128] = 1; k++; // Include the smoothness equations for (int i=0; i<n-2; i++) { A[k][i] = lambda * weight(i+1); A[k][i+1] = -2.0*lambda*weight(i+1); A[k][i+2] = lambda * weight(i+1); k++; } // Reshape matrix (in row order) so that it can be used with lapack double* system = new double[nlins*ncols]; for (int k=0; k<nlins*ncols; k++) { int i = k / ncols; int j = k % ncols; system[k] = A[i][j]; } // Solve the system using SVD int sz = std::min(nlins, ncols); double* s = new double[sz]; lapack_int rank; LAPACKE_dgelsd(LAPACK_ROW_MAJOR, nlins, ncols, 1, system, ncols, b, 1, s, -1.0, &rank); // Log exposure for pixel values 0 through 255 g.resize(n, 0.0); for (int i=0; i<n; i++) { g[i] = (float) b[i]; } // Log film irradiance for every sample pixel lE.resize(nlins-n, 0.0); #ifdef DEBUG std::cout << "N=" << N << "\nP=" << P << "\nsize of lE=" << nlins-n << std::endl; #endif for (int i=0; i<nlins-n; i++) { lE[i] = (float) b[n+i]; } };
template <> inline int gelsd(const char order, const int K, const int N, const int M, double *A, const int LDA, double *B, const int LDB, double *S, double R, int *RANK) { return LAPACKE_dgelsd(order, K, N, M, A, LDA, B, LDB, S, R, RANK); }