mirror of
https://github.com/opencv/opencv.git
synced 2025-06-07 17:44:04 +08:00
Merge pull request #27396 from abhishek-gola:hdr_bug_fix
Fix NaNs in HDR Triangle Weights and Tonemapping and Update LDR Ground Truth in tutorial #27396 The PR closes #27392 Updated the triangle weights to use a small epsilon value instead of zero to prevent NaN issues in HDR processing. Also fixed a float-to-double division issue by explicitly casting double values to float, which was previously producing garbage values and leading to NaNs in tonemapping. The current LDR ground truth image used in the tutorial [ldr.png](https://github.com/opencv/opencv/blob/4.x/doc/tutorials/others/images/ldr.png) was originally generated using TonemapDurand (check this commit833f8d16fa
), which was moved to opencv_contrib a long time ago in this commit:742f22c09b
. However, the current Tonemap implementation in OpenCV main only performs normalization and gamma correction, which produces noticeably different results. This PR updates the LDR grouth truth image in tutorial with the result of TonemapDrago, and tutorials to use TonemapDrago as Tonemap gives a darker image. Tonemap output:  TonemapDrago output:  ### Pull Request Readiness Checklist See details at https://github.com/opencv/opencv/wiki/How_to_contribute#making-a-good-pull-request - [x] I agree to contribute to the project under Apache 2 License. - [x] To the best of my knowledge, the proposed patch is not based on a code under GPL or another license that is incompatible with OpenCV - [x] The PR is proposed to the proper branch - [x] There is a reference to the original bug report and related work - [x] There is accuracy test, performance test and test data in opencv_extra repository, if applicable Patch to opencv_extra has the same branch name. - [x] The feature is well documented and sample code can be built with the project CMake
This commit is contained in:
parent
9e18169959
commit
aef6ae4872
Binary file not shown.
Before Width: | Height: | Size: 560 KiB After Width: | Height: | Size: 535 KiB |
@ -65,10 +65,14 @@ Mat triangleWeights()
|
||||
Mat w(LDR_SIZE, 1, CV_32F);
|
||||
int half = LDR_SIZE / 2;
|
||||
int maxVal = LDR_SIZE - 1;
|
||||
for (int i = 0; i < LDR_SIZE; i++)
|
||||
float epsilon = 1e-6f;
|
||||
w.at<float>(0) = epsilon;
|
||||
w.at<float>(LDR_SIZE-1) = epsilon;
|
||||
for (int i = 1; i < LDR_SIZE-1; i++){
|
||||
w.at<float>(i) = (i < half)
|
||||
? static_cast<float>(i)
|
||||
: static_cast<float>(maxVal - i);
|
||||
}
|
||||
return w;
|
||||
}
|
||||
|
||||
|
@ -72,8 +72,10 @@ public:
|
||||
|
||||
double min, max;
|
||||
minMaxLoc(src, &min, &max);
|
||||
float fmin = static_cast<float>(min);
|
||||
float fmax = static_cast<float>(max);
|
||||
if(max - min > DBL_EPSILON) {
|
||||
dst = (src - min) / (max - min);
|
||||
dst = (src - fmin) / (fmax - fmin);
|
||||
} else {
|
||||
src.copyTo(dst);
|
||||
}
|
||||
@ -139,8 +141,9 @@ public:
|
||||
gray_img /= mean;
|
||||
log_img.release();
|
||||
|
||||
double max;
|
||||
minMaxLoc(gray_img, NULL, &max);
|
||||
double dmax;
|
||||
minMaxLoc(gray_img, NULL, &dmax);
|
||||
float max = static_cast<float>(dmax);
|
||||
CV_Assert(max > 0);
|
||||
|
||||
Mat map;
|
||||
@ -150,7 +153,6 @@ public:
|
||||
log(2.0f + 8.0f * div, div);
|
||||
map = map.mul(1.0f / div);
|
||||
div.release();
|
||||
|
||||
mapLuminance(img, img, gray_img, map, saturation);
|
||||
|
||||
linear->setGamma(gamma);
|
||||
@ -223,12 +225,14 @@ public:
|
||||
log_(gray_img, log_img);
|
||||
|
||||
float log_mean = static_cast<float>(sum(log_img)[0] / log_img.total());
|
||||
double log_min, log_max;
|
||||
minMaxLoc(log_img, &log_min, &log_max);
|
||||
double dlog_min, dlog_max;
|
||||
minMaxLoc(log_img, &dlog_min, &dlog_max);
|
||||
float log_max = static_cast<float>(dlog_max);
|
||||
float log_min = static_cast<float>(dlog_min);
|
||||
log_img.release();
|
||||
|
||||
double key = static_cast<float>((log_max - log_mean) / (log_max - log_min));
|
||||
float map_key = 0.3f + 0.7f * pow(static_cast<float>(key), 1.4f);
|
||||
float key = (log_max - log_mean) / (log_max - log_min);
|
||||
float map_key = 0.3f + 0.7f * pow(key, 1.4f);
|
||||
intensity = exp(-intensity);
|
||||
Scalar chan_mean = mean(img);
|
||||
float gray_mean = static_cast<float>(mean(gray_img)[0]);
|
||||
@ -287,9 +291,9 @@ protected:
|
||||
float gamma, intensity, light_adapt, color_adapt;
|
||||
};
|
||||
|
||||
Ptr<TonemapReinhard> createTonemapReinhard(float gamma, float contrast, float sigma_color, float sigma_space)
|
||||
Ptr<TonemapReinhard> createTonemapReinhard(float gamma, float intensity, float light_adapt, float color_adapt)
|
||||
{
|
||||
return makePtr<TonemapReinhardImpl>(gamma, contrast, sigma_color, sigma_space);
|
||||
return makePtr<TonemapReinhardImpl>(gamma, intensity, light_adapt, color_adapt);
|
||||
}
|
||||
|
||||
class TonemapMantiukImpl CV_FINAL : public TonemapMantiuk
|
||||
|
@ -35,7 +35,7 @@ int main(int argc, char**argv)
|
||||
|
||||
//! [Tonemap HDR image]
|
||||
Mat ldr;
|
||||
Ptr<Tonemap> tonemap = createTonemap(2.2f);
|
||||
Ptr<TonemapDrago> tonemap = createTonemapDrago(2.2f);
|
||||
tonemap->process(hdr, ldr);
|
||||
//! [Tonemap HDR image]
|
||||
|
||||
|
@ -40,7 +40,7 @@ hdr = merge_debevec.process(images, times, response)
|
||||
## [Make HDR image]
|
||||
|
||||
## [Tonemap HDR image]
|
||||
tonemap = cv.createTonemap(2.2)
|
||||
tonemap = cv.createTonemapDrago(2.2)
|
||||
ldr = tonemap.process(hdr)
|
||||
## [Tonemap HDR image]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user