From dfb6069ad9857472a4b7b2d605b6a462f0b6884f Mon Sep 17 00:00:00 2001 From: "mikhail.shtennikov" Date: Mon, 15 Apr 2024 02:59:58 +0500 Subject: [PATCH] Inpainting floating point values with Telea's algorithm gives unexpected results --- modules/photo/src/inpaint.cpp | 19 +++++++++++++++---- modules/photo/test/test_inpaint.cpp | 14 +++++++------- 2 files changed, 22 insertions(+), 11 deletions(-) diff --git a/modules/photo/src/inpaint.cpp b/modules/photo/src/inpaint.cpp index a763b63f33..d2d495e57e 100644 --- a/modules/photo/src/inpaint.cpp +++ b/modules/photo/src/inpaint.cpp @@ -46,6 +46,7 @@ // */ #include +#include #include "precomp.hpp" #include "opencv2/imgproc/imgproc_c.h" @@ -55,6 +56,16 @@ #define CV_MAT_ELEM_PTR_FAST( mat, row, col, pix_size ) \ ((mat).data.ptr + (size_t)(mat).step*(row) + (pix_size)*(col)) +template +typename std::enable_if::value, T>::type round_cast(float val) { + return cv::saturate_cast(val); +} + +template +typename std::enable_if::value, T>::type round_cast(float val) { + return cv::saturate_cast(val + 0.5); +} + inline float min4( float a, float b, float c, float d ) { @@ -339,8 +350,8 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu } } for (color=0; color<=2; color++) { - sat = (float)((Ia[color]/s[color]+(Jx[color]+Jy[color])/(sqrt(Jx[color]*Jx[color]+Jy[color]*Jy[color])+1.0e-20f)+0.5f)); - CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = cv::saturate_cast(sat); + sat = (float)(Ia[color]/s[color]+(Jx[color]+Jy[color])/(sqrt(Jx[color]*Jx[color]+Jy[color]*Jy[color])+1.0e-20f)); + CV_MAT_3COLOR_ELEM(*out,uchar,i-1,j-1,color) = round_cast(sat); } CV_MAT_ELEM(*f,uchar,i,j) = BAND; @@ -449,9 +460,9 @@ icvTeleaInpaintFMM(const CvMat *f, CvMat *t, CvMat *out, int range, CvPriorityQu } } } - sat = (float)((Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)+0.5f)); + sat = (float)(Ia/s+(Jx+Jy)/(sqrt(Jx*Jx+Jy*Jy)+1.0e-20f)); { - CV_MAT_ELEM(*out,data_type,i-1,j-1) = cv::saturate_cast(sat); + CV_MAT_ELEM(*out,data_type,i-1,j-1) = round_cast(sat); } } diff --git a/modules/photo/test/test_inpaint.cpp b/modules/photo/test/test_inpaint.cpp index 58806cbbc2..1536490693 100644 --- a/modules/photo/test/test_inpaint.cpp +++ b/modules/photo/test/test_inpaint.cpp @@ -116,9 +116,9 @@ void CV_InpaintTest::run( int ) TEST(Photo_Inpaint, regression) { CV_InpaintTest test; test.safe_run(); } -typedef testing::TestWithParam > formats; +typedef testing::TestWithParam > formats; -TEST_P(formats, 1c) +TEST_P(formats, basic) { const int type = get<0>(GetParam()); Mat src(100, 100, type); @@ -126,18 +126,18 @@ TEST_P(formats, 1c) Mat ref = src.clone(); Mat dst, mask = Mat::zeros(src.size(), CV_8U); - circle(src, Point(50, 50), 5, Scalar(200), 6); - circle(mask, Point(50, 50), 5, Scalar(200), 6); + circle(src, Point(50, 50), 5, Scalar::all(200), 6); + circle(mask, Point(50, 50), 5, Scalar::all(200), 6); inpaint(src, mask, dst, 10, INPAINT_NS); Mat dst2; inpaint(src, mask, dst2, 10, INPAINT_TELEA); - ASSERT_LE(cv::norm(dst, ref, NORM_INF), 3.); - ASSERT_LE(cv::norm(dst2, ref, NORM_INF), 3.); + ASSERT_EQ(cv::norm(dst, ref, NORM_INF), 0.); + ASSERT_EQ(cv::norm(dst2, ref, NORM_INF), 0.); } -INSTANTIATE_TEST_CASE_P(Photo_Inpaint, formats, testing::Values(CV_32F, CV_16U, CV_8U)); +INSTANTIATE_TEST_CASE_P(Photo_Inpaint, formats, testing::Values(CV_32FC1, CV_16UC1, CV_8UC1, CV_8UC3)); TEST(Photo_InpaintBorders, regression) {