Merge pull request #27270 from gursimarsingh:bug_fix_unstable_crf

Bug fix unstable crf #27270

### 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

The PR resolves the issue for triangle Weights used by debevec algorithm being non zero at extremes. 
It resolves #24966 

The fix needs ground truth data to be changed in order to pass existing tests. PR to opencv_extra: https://github.com/opencv/opencv_extra/pull/1253
This commit is contained in:
Gursimar Singh 2025-05-21 11:10:11 +05:30 committed by GitHub
parent d00738d97c
commit c3fe92d813
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 50 additions and 9 deletions

View File

@ -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<float>(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<float>(i) = (i < half)
? static_cast<float>(i)
: static_cast<float>(maxVal - i);
return w;
}

View File

@ -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<Tonemap> 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<CalibrateDebevec> 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<Mat> all_images;
vector<float> all_times;
loadExposureSeq(test_path + "exposures/", all_images, all_times);
// Use a balanced subset of exposures
vector<int> selected_indices = {1,2,3,4,5};
vector<Mat> images;
vector<float> 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<int> sample_points = {200,300,400};
vector<Mat> responses;
for (int samples : sample_points) {
Ptr<CalibrateDebevec> 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