diff --git a/modules/photo/src/hdr_common.cpp b/modules/photo/src/hdr_common.cpp index 983efe3792..5e4bea9d85 100644 --- a/modules/photo/src/hdr_common.cpp +++ b/modules/photo/src/hdr_common.cpp @@ -63,10 +63,12 @@ Mat triangleWeights() { // hat function Mat w(LDR_SIZE, 1, CV_32F); - int half = LDR_SIZE / 2; - for(int i = 0; i < LDR_SIZE; i++) { - w.at(i) = i < half ? i + 1.0f : LDR_SIZE - i; - } + int half = LDR_SIZE / 2; + int maxVal = LDR_SIZE - 1; + for (int i = 0; i < LDR_SIZE; i++) + w.at(i) = (i < half) + ? static_cast(i) + : static_cast(maxVal - i); return w; } diff --git a/modules/photo/test/test_hdr.cpp b/modules/photo/test/test_hdr.cpp index a26e83e49e..264a7d7257 100644 --- a/modules/photo/test/test_hdr.cpp +++ b/modules/photo/test/test_hdr.cpp @@ -187,11 +187,9 @@ TEST(Photo_MergeDebevec, regression) Mat result, expected; loadImage(test_path + "merge/debevec.hdr", expected); merge->process(images, result, times, response); - Ptr map = createTonemap(); map->process(result, result); map->process(expected, expected); - checkEqual(expected, result, 1e-2f, "Debevec"); } @@ -221,16 +219,15 @@ TEST(Photo_CalibrateDebevec, regression) loadExposureSeq(test_path + "exposures/", images, times); loadResponseCSV(test_path + "calibrate/debevec.csv", expected); Ptr calibrate = createCalibrateDebevec(); - calibrate->process(images, response, times); Mat diff = abs(response - expected); diff = diff.mul(1.0f / response); double max; minMaxLoc(diff, NULL, &max); #if defined(__arm__) || defined(__aarch64__) - ASSERT_LT(max, 0.2); + ASSERT_LT(max, 0.25); #else - ASSERT_LT(max, 0.1); + ASSERT_LT(max, 0.15); #endif } @@ -266,4 +263,46 @@ TEST(Photo_CalibrateRobertson, bug_18180) EXPECT_EQ(0.0, cv::norm(response, response_no_nans, NORM_L2)); } +TEST(Photo_CalibrateDebevec, bug_24966) +{ + string test_path = string(cvtest::TS::ptr()->get_data_path()) + "hdr/"; + vector all_images; + vector all_times; + loadExposureSeq(test_path + "exposures/", all_images, all_times); + // Use a balanced subset of exposures + vector selected_indices = {1,2,3,4,5}; + vector images; + vector times; + for (int idx : selected_indices) { + images.push_back(all_images[idx]); + times.push_back(all_times[idx]); + } + // Run CRF estimation for different sample points + vector sample_points = {200,300,400}; + vector responses; + for (int samples : sample_points) { + Ptr calibrate = createCalibrateDebevec(samples); + Mat response; + calibrate->process(images, response, times); + Mat roi = response.rowRange(15, 240); //Checking CRF only in the middle of the image + responses.push_back(roi); + } + + // Compare consecutive pairs of CRFs + for (size_t i = 0; i < responses.size()-1; ++i) { + Mat diff = abs(responses[i] - responses[i+1]); + double max_diff; + minMaxLoc(diff, nullptr, &max_diff); + cout << "max_diff = " << max_diff << endl; + #if defined(__aarch64__) && defined(__APPLE__) + ASSERT_LT(max_diff, 10) << "CRF instability detected between samples=" + << sample_points[i] << " and " << sample_points[i+1] + << " (max diff = " << max_diff << ")"; + #else + ASSERT_LT(max_diff, 5) << "CRF instability detected between samples=" + << sample_points[i] << " and " << sample_points[i+1] + << " (max diff = " << max_diff << ")"; + #endif + } +} }} // namespace