From a102b24285de7abc982582a63ed72e027cea87cf Mon Sep 17 00:00:00 2001 From: Alexander Smorkalov Date: Wed, 19 Jun 2024 14:23:53 +0300 Subject: [PATCH] Added LUT for FP16 and accuracy test. --- modules/core/src/lut.cpp | 7 ++- modules/core/test/test_arithm.cpp | 98 +++++++++++++++++++++++++++++++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/modules/core/src/lut.cpp b/modules/core/src/lut.cpp index 031f113bec..62c02d2b84 100644 --- a/modules/core/src/lut.cpp +++ b/modules/core/src/lut.cpp @@ -56,6 +56,11 @@ static void LUT8u_32s( const uchar* src, const int* lut, int* dst, int len, int LUT8u_( src, lut, dst, len, cn, lutcn ); } +static void LUT8u_16f( const uchar* src, const hfloat* lut, hfloat* dst, int len, int cn, int lutcn ) +{ + LUT8u_( src, lut, dst, len, cn, lutcn ); +} + static void LUT8u_32f( const uchar* src, const float* lut, float* dst, int len, int cn, int lutcn ) { LUT8u_( src, lut, dst, len, cn, lutcn ); @@ -71,7 +76,7 @@ typedef void (*LUTFunc)( const uchar* src, const uchar* lut, uchar* dst, int len static LUTFunc lutTab[CV_DEPTH_MAX] = { (LUTFunc)LUT8u_8u, (LUTFunc)LUT8u_8s, (LUTFunc)LUT8u_16u, (LUTFunc)LUT8u_16s, - (LUTFunc)LUT8u_32s, (LUTFunc)LUT8u_32f, (LUTFunc)LUT8u_64f, 0 + (LUTFunc)LUT8u_32s, (LUTFunc)LUT8u_32f, (LUTFunc)LUT8u_64f, (LUTFunc)LUT8u_16f }; #ifdef HAVE_OPENCL diff --git a/modules/core/test/test_arithm.cpp b/modules/core/test/test_arithm.cpp index 6e4151c0cc..20c0cbce26 100644 --- a/modules/core/test/test_arithm.cpp +++ b/modules/core/test/test_arithm.cpp @@ -3196,5 +3196,103 @@ INSTANTIATE_TEST_CASE_P(Core_CartPolar, Core_PolarToCart_inplace, ) ); +CV_ENUM(LutMatType, CV_8U, CV_16U, CV_16F, CV_32S, CV_32F, CV_64F) + +struct Core_LUT: public testing::TestWithParam +{ + template + cv::Mat referenceWithType(cv::Mat input, cv::Mat table) + { + cv::Mat ref(input.size(), CV_MAKE_TYPE(table.type(), ch)); + for (int i = 0; i < input.rows; i++) + { + for (int j = 0; j < input.cols; j++) + { + if(ch == 1) + { + ref.at(i, j) = table.at(input.at(i, j)); + } + else + { + Vec val; + for (int k = 0; k < ch; k++) + { + val[k] = table.at(input.at>(i, j)[k]); + } + ref.at>(i, j) = val; + } + } + } + return ref; + } + + template + cv::Mat reference(cv::Mat input, cv::Mat table) + { + if (table.type() == CV_8U) + { + return referenceWithType(input, table); + } + else if (table.type() == CV_16U) + { + return referenceWithType(input, table); + } + else if (table.type() == CV_16F) + { + return referenceWithType(input, table); + } + else if (table.type() == CV_32S) + { + return referenceWithType(input, table); + } + else if (table.type() == CV_32F) + { + return referenceWithType(input, table); + } + else if (table.type() == CV_64F) + { + return referenceWithType(input, table); + } + + return cv::Mat(); + } +}; + +TEST_P(Core_LUT, accuracy) +{ + int type = GetParam(); + cv::Mat input(117, 113, CV_8UC1); + randu(input, 0, 256); + + cv::Mat table(1, 256, CV_MAKE_TYPE(type, 1)); + randu(table, 0, 127); + + cv::Mat output; + cv::LUT(input, table, output); + + cv::Mat gt = reference(input, table); + + ASSERT_EQ(0, cv::norm(output, gt, cv::NORM_INF)); +} + +TEST_P(Core_LUT, accuracy_multi) +{ + int type = (int)GetParam(); + cv::Mat input(117, 113, CV_8UC3); + randu(input, 0, 256); + + cv::Mat table(1, 256, CV_MAKE_TYPE(type, 1)); + randu(table, 0, 127); + + cv::Mat output; + cv::LUT(input, table, output); + + cv::Mat gt = reference<3>(input, table); + + ASSERT_EQ(0, cv::norm(output, gt, cv::NORM_INF)); +} + + +INSTANTIATE_TEST_CASE_P(/**/, Core_LUT, LutMatType::all()); }} // namespace