Merge pull request #25413 from Linaname:#25404

Correct inpainting floating point values with Telea's algorithm
This commit is contained in:
Alexander Smorkalov 2024-04-16 12:16:35 +03:00 committed by GitHub
commit 66fb5021e9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 22 additions and 11 deletions

View File

@ -46,6 +46,7 @@
// */
#include <queue>
#include <type_traits>
#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 T>
typename std::enable_if<std::is_floating_point<T>::value, T>::type round_cast(float val) {
return cv::saturate_cast<T>(val);
}
template<typename T>
typename std::enable_if<!std::is_floating_point<T>::value, T>::type round_cast(float val) {
return cv::saturate_cast<T>(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<uchar>(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<uchar>(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<data_type>(sat);
CV_MAT_ELEM(*out,data_type,i-1,j-1) = round_cast<data_type>(sat);
}
}

View File

@ -116,9 +116,9 @@ void CV_InpaintTest::run( int )
TEST(Photo_Inpaint, regression) { CV_InpaintTest test; test.safe_run(); }
typedef testing::TestWithParam<tuple<int> > formats;
typedef testing::TestWithParam<tuple<perf::MatType> > 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)
{