void process(InputArrayOfArrays src, OutputArray dst, InputArray _times) { std::vector<Mat> images; src.getMatVector(images); Mat times = _times.getMat(); CV_Assert(images.size() == times.total()); checkImageDimensions(images); CV_Assert(images[0].depth() == CV_8U); int channels = images[0].channels(); int CV_32FCC = CV_MAKETYPE(CV_32F, channels); dst.create(LDR_SIZE, 1, CV_32FCC); Mat response = dst.getMat(); response = linearResponse(3) / (LDR_SIZE / 2.0f); Mat card = Mat::zeros(LDR_SIZE, 1, CV_32FCC); for(size_t i = 0; i < images.size(); i++) { uchar *ptr = images[i].ptr(); for(size_t pos = 0; pos < images[i].total(); pos++) { for(int c = 0; c < channels; c++, ptr++) { card.at<Vec3f>(*ptr)[c] += 1; } } } card = 1.0 / card; Ptr<MergeRobertson> merge = createMergeRobertson(); for(int iter = 0; iter < max_iter; iter++) { radiance = Mat::zeros(images[0].size(), CV_32FCC); merge->process(images, radiance, times, response); Mat new_response = Mat::zeros(LDR_SIZE, 1, CV_32FC3); for(size_t i = 0; i < images.size(); i++) { uchar *ptr = images[i].ptr(); float* rad_ptr = radiance.ptr<float>(); for(size_t pos = 0; pos < images[i].total(); pos++) { for(int c = 0; c < channels; c++, ptr++, rad_ptr++) { new_response.at<Vec3f>(*ptr)[c] += times.at<float>((int)i) * *rad_ptr; } } } new_response = new_response.mul(card); for(int c = 0; c < 3; c++) { float middle = new_response.at<Vec3f>(LDR_SIZE / 2)[c]; for(int i = 0; i < LDR_SIZE; i++) { new_response.at<Vec3f>(i)[c] /= middle; } } float diff = static_cast<float>(sum(sum(abs(new_response - response)))[0] / channels); new_response.copyTo(response); if(diff < threshold) { break; } } }
void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response) { std::vector<Mat> images; src.getMatVector(images); Mat times = _times.getMat(); CV_Assert(images.size() == times.total()); checkImageDimensions(images); CV_Assert(images[0].depth() == CV_8U); int channels = images[0].channels(); int CV_32FCC = CV_MAKETYPE(CV_32F, channels); dst.create(images[0].size(), CV_32FCC); Mat result = dst.getMat(); Mat response = input_response.getMat(); if(response.empty()) { float middle = LDR_SIZE / 2.0f; response = linearResponse(channels) / middle; } CV_Assert(response.rows == LDR_SIZE && response.cols == 1 && response.channels() == channels); result = Mat::zeros(images[0].size(), CV_32FCC); Mat wsum = Mat::zeros(images[0].size(), CV_32FCC); for(size_t i = 0; i < images.size(); i++) { Mat im, w; LUT(images[i], weight, w); LUT(images[i], response, im); result += times.at<float>((int)i) * w.mul(im); wsum += times.at<float>((int)i) * times.at<float>((int)i) * w; } result = result.mul(1 / wsum); }
void process(InputArrayOfArrays src, OutputArray dst, InputArray _times, InputArray input_response) { std::vector<Mat> images; src.getMatVector(images); Mat times = _times.getMat(); CV_Assert(images.size() == times.total()); checkImageDimensions(images); CV_Assert(images[0].depth() == CV_8U); int channels = images[0].channels(); Size size = images[0].size(); int CV_32FCC = CV_MAKETYPE(CV_32F, channels); dst.create(images[0].size(), CV_32FCC); Mat result = dst.getMat(); Mat response = input_response.getMat(); if(response.empty()) { response = linearResponse(channels); response.at<Vec3f>(0) = response.at<Vec3f>(1); } Mat log_response; log(response, log_response); CV_Assert(log_response.rows == LDR_SIZE && log_response.cols == 1 && log_response.channels() == channels); Mat exp_values(times); log(exp_values, exp_values); result = Mat::zeros(size, CV_32FCC); std::vector<Mat> result_split; split(result, result_split); Mat weight_sum = Mat::zeros(size, CV_32F); for(size_t i = 0; i < images.size(); i++) { std::vector<Mat> splitted; split(images[i], splitted); Mat w = Mat::zeros(size, CV_32F); for(int c = 0; c < channels; c++) { LUT(splitted[c], weights, splitted[c]); w += splitted[c]; } w /= channels; Mat response_img; LUT(images[i], log_response, response_img); split(response_img, splitted); for(int c = 0; c < channels; c++) { result_split[c] += w.mul(splitted[c] - exp_values.at<float>((int)i)); } weight_sum += w; } weight_sum = 1.0f / weight_sum; for(int c = 0; c < channels; c++) { result_split[c] = result_split[c].mul(weight_sum); } merge(result_split, result); exp(result, result); }