test_domain_transform.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. // This file is part of OpenCV project.
  2. // It is subject to the license terms in the LICENSE file found in the top-level directory
  3. // of this distribution and at http://opencv.org/license.html.
  4. #include "test_precomp.hpp"
  5. namespace opencv_test { namespace {
  6. static string getOpenCVExtraDir()
  7. {
  8. return cvtest::TS::ptr()->get_data_path();
  9. }
  10. CV_ENUM(SupportedTypes, CV_8UC1, CV_8UC3, CV_32FC1); // reduced set
  11. CV_ENUM(ModeType, DTF_NC, DTF_IC, DTF_RF)
  12. typedef tuple<Size, ModeType, SupportedTypes, SupportedTypes> DTParams;
  13. Mat convertTypeAndSize(Mat src, int dstType, Size dstSize)
  14. {
  15. Mat dst;
  16. CV_Assert(src.channels() == 3);
  17. int dstChannels = CV_MAT_CN(dstType);
  18. if (dstChannels == 1)
  19. {
  20. cvtColor(src, dst, COLOR_BGR2GRAY);
  21. }
  22. else if (dstChannels == 2)
  23. {
  24. Mat srcCn[3];
  25. split(src, srcCn);
  26. merge(srcCn, 2, dst);
  27. }
  28. else if (dstChannels == 3)
  29. {
  30. dst = src.clone();
  31. }
  32. else if (dstChannels == 4)
  33. {
  34. Mat srcCn[4];
  35. split(src, srcCn);
  36. srcCn[3] = srcCn[0].clone();
  37. merge(srcCn, 4, dst);
  38. }
  39. dst.convertTo(dst, dstType);
  40. resize(dst, dst, dstSize, 0, 0, dstType == CV_32FC1 ? INTER_LINEAR : INTER_LINEAR_EXACT);
  41. return dst;
  42. }
  43. TEST(DomainTransformTest, SplatSurfaceAccuracy)
  44. {
  45. static int dtModes[] = {DTF_NC, DTF_RF, DTF_IC};
  46. RNG rnd(0);
  47. for (int i = 0; i < 15; i++)
  48. {
  49. Size sz(rnd.uniform(512, 1024), rnd.uniform(512, 1024));
  50. int guideCn = rnd.uniform(1, 4);
  51. Mat guide(sz, CV_MAKE_TYPE(CV_32F, guideCn));
  52. randu(guide, 0, 255);
  53. Scalar surfaceValue;
  54. int srcCn = rnd.uniform(1, 4);
  55. rnd.fill(surfaceValue, RNG::UNIFORM, 0, 255);
  56. Mat src(sz, CV_MAKE_TYPE(CV_8U, srcCn), surfaceValue);
  57. double sigma_s = rnd.uniform(1.0, 100.0);
  58. double sigma_r = rnd.uniform(1.0, 100.0);
  59. int mode = dtModes[i%3];
  60. Mat res;
  61. dtFilter(guide, src, res, sigma_s, sigma_r, mode, 1);
  62. double normL1 = cvtest::norm(src, res, NORM_L1)/src.total()/src.channels();
  63. EXPECT_LE(normL1, 1.0/64);
  64. }
  65. }
  66. typedef TestWithParam<DTParams> DomainTransformTest;
  67. TEST_P(DomainTransformTest, MultiThreadReproducibility)
  68. {
  69. if (cv::getNumberOfCPUs() == 1)
  70. return;
  71. double MAX_DIF = 1.0;
  72. double MAX_MEAN_DIF = 1.0 / 256.0;
  73. int loopsCount = 2;
  74. RNG rng(0);
  75. DTParams params = GetParam();
  76. Size size = get<0>(params);
  77. int mode = get<1>(params);
  78. int guideType = get<2>(params);
  79. int srcType = get<3>(params);
  80. Mat original = imread(getOpenCVExtraDir() + "cv/edgefilter/statue.png");
  81. Mat guide = convertTypeAndSize(original, guideType, size);
  82. Mat src = convertTypeAndSize(original, srcType, size);
  83. int nThreads = cv::getNumThreads();
  84. if (nThreads == 1)
  85. throw SkipTestException("Single thread environment");
  86. for (int iter = 0; iter <= loopsCount; iter++)
  87. {
  88. double ss = rng.uniform(0.0, 100.0);
  89. double sc = rng.uniform(0.0, 100.0);
  90. cv::setNumThreads(nThreads);
  91. Mat resMultithread;
  92. dtFilter(guide, src, resMultithread, ss, sc, mode);
  93. cv::setNumThreads(1);
  94. Mat resSingleThread;
  95. dtFilter(guide, src, resSingleThread, ss, sc, mode);
  96. EXPECT_LE(cv::norm(resSingleThread, resMultithread, NORM_INF), MAX_DIF);
  97. EXPECT_LE(cv::norm(resSingleThread, resMultithread, NORM_L1), MAX_MEAN_DIF*src.total());
  98. }
  99. }
  100. INSTANTIATE_TEST_CASE_P(FullSet, DomainTransformTest,
  101. Combine(Values(szODD, szQVGA), ModeType::all(), SupportedTypes::all(), SupportedTypes::all())
  102. );
  103. template<typename SrcVec>
  104. Mat getChessMat1px(Size sz, double whiteIntensity = 255)
  105. {
  106. typedef typename DataType<SrcVec>::channel_type SrcType;
  107. Mat dst(sz, traits::Type<SrcVec>::value);
  108. SrcVec black = SrcVec::all(0);
  109. SrcVec white = SrcVec::all((SrcType)whiteIntensity);
  110. for (int i = 0; i < dst.rows; i++)
  111. for (int j = 0; j < dst.cols; j++)
  112. dst.at<SrcVec>(i, j) = ((i + j) % 2) ? white : black;
  113. return dst;
  114. }
  115. TEST(DomainTransformTest, ChessBoard_NC_accuracy)
  116. {
  117. RNG rng(0);
  118. double MAX_DIF = 1;
  119. Size sz = szVGA;
  120. double ss = 80;
  121. double sc = 60;
  122. Mat srcb = randomMat(rng, sz, CV_8UC4, 0, 255, true);
  123. Mat srcf = randomMat(rng, sz, CV_32FC4, 0, 255, true);
  124. Mat chessb = getChessMat1px<Vec3b>(sz);
  125. Mat dstb, dstf;
  126. dtFilter(chessb, srcb.clone(), dstb, ss, sc, DTF_NC);
  127. dtFilter(chessb, srcf.clone(), dstf, ss, sc, DTF_NC);
  128. EXPECT_LE(cv::norm(srcb, dstb, NORM_INF), MAX_DIF);
  129. EXPECT_LE(cv::norm(srcf, dstf, NORM_INF), MAX_DIF);
  130. }
  131. TEST(DomainTransformTest, BoxFilter_NC_accuracy)
  132. {
  133. double MAX_DIF = 1;
  134. int radius = 5;
  135. double sc = 1.0;
  136. double ss = 1.01*radius / sqrt(3.0);
  137. Mat src = imread(getOpenCVExtraDir() + "cv/edgefilter/statue.png");
  138. ASSERT_TRUE(!src.empty());
  139. Mat1b guide(src.size(), 200);
  140. Mat res_dt, res_box;
  141. blur(src, res_box, Size(2 * radius + 1, 2 * radius + 1));
  142. dtFilter(guide, src, res_dt, ss, sc, DTF_NC, 1);
  143. EXPECT_LE(cv::norm(res_dt, res_box, NORM_L2), MAX_DIF*src.total());
  144. }
  145. TEST(DomainTransformTest, AuthorReferenceAccuracy)
  146. {
  147. string dir = getOpenCVExtraDir() + "cv/edgefilter";
  148. double ss = 30;
  149. double sc = 0.2 * 255;
  150. Mat src = imread(dir + "/statue.png");
  151. Mat ref_NC = imread(dir + "/dt/authors_statue_NC_ss30_sc0.2.png");
  152. Mat ref_IC = imread(dir + "/dt/authors_statue_IC_ss30_sc0.2.png");
  153. Mat ref_RF = imread(dir + "/dt/authors_statue_RF_ss30_sc0.2.png");
  154. ASSERT_FALSE(src.empty());
  155. ASSERT_FALSE(ref_NC.empty());
  156. ASSERT_FALSE(ref_IC.empty());
  157. ASSERT_FALSE(ref_RF.empty());
  158. Mat res_NC, res_IC, res_RF;
  159. dtFilter(src, src, res_NC, ss, sc, DTF_NC);
  160. dtFilter(src, src, res_IC, ss, sc, DTF_IC);
  161. dtFilter(src, src, res_RF, ss, sc, DTF_RF);
  162. double totalMaxError = 1.0/64.0*src.total();
  163. EXPECT_LE(cvtest::norm(res_NC, ref_NC, NORM_L2), totalMaxError);
  164. EXPECT_LE(cvtest::norm(res_NC, ref_NC, NORM_INF), 1);
  165. EXPECT_LE(cvtest::norm(res_IC, ref_IC, NORM_L2), totalMaxError);
  166. EXPECT_LE(cvtest::norm(res_IC, ref_IC, NORM_INF), 1);
  167. EXPECT_LE(cvtest::norm(res_RF, ref_RF, NORM_L2), totalMaxError);
  168. EXPECT_LE(cvtest::norm(res_IC, ref_IC, NORM_INF), 1);
  169. }
  170. }} // namespace