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
6 namespace opencv_test { namespace {
7
getOpenCVExtraDir()8 static std::string getOpenCVExtraDir()
9 {
10 return cvtest::TS::ptr()->get_data_path();
11 }
12
checkSimilarity(InputArray src,InputArray ref)13 static void checkSimilarity(InputArray src, InputArray ref)
14 {
15 // Doesn't work with bilateral filter: EXPECT_LE(cvtest::norm(src, ref, NORM_INF), 1.0);
16 EXPECT_LE(cvtest::norm(src, ref, NORM_L2 | NORM_RELATIVE), 1e-3);
17 }
18
convertTypeAndSize(Mat src,int dstType,Size dstSize)19 static Mat convertTypeAndSize(Mat src, int dstType, Size dstSize)
20 {
21 Mat dst;
22 int srcCnNum = src.channels();
23 int dstCnNum = CV_MAT_CN(dstType);
24
25 if (srcCnNum == dstCnNum)
26 {
27 src.copyTo(dst);
28 }
29 else if (srcCnNum == 3 && dstCnNum == 1)
30 {
31 cvtColor(src, dst, COLOR_BGR2GRAY);
32 }
33 else if (srcCnNum == 1 && dstCnNum == 3)
34 {
35 cvtColor(src, dst, COLOR_GRAY2BGR);
36 }
37 else
38 {
39 CV_Error(Error::BadNumChannels, "Bad num channels in src");
40 }
41
42 dst.convertTo(dst, dstType);
43 resize(dst, dst, dstSize, 0, 0, INTER_LINEAR_EXACT);
44
45 return dst;
46 }
47
48 //////////////////////////////////////////////////////////////////////////
49 //////////////////////////////////////////////////////////////////////////
50
51 typedef tuple<double, MatType, int> RGFParams;
52 typedef TestWithParam<RGFParams> RollingGuidanceFilterTest;
53
TEST_P(RollingGuidanceFilterTest,SplatSurfaceAccuracy)54 TEST_P(RollingGuidanceFilterTest, SplatSurfaceAccuracy)
55 {
56 RGFParams params = GetParam();
57 double sigmaS = get<0>(params);
58 int depth = get<1>(params);
59 int srcCn = get<2>(params);
60
61 RNG rnd(0);
62
63 Size sz(rnd.uniform(512,1024), rnd.uniform(512,1024));
64
65 for (int i = 0; i < 5; i++)
66 {
67 Scalar surfaceValue;
68 rnd.fill(surfaceValue, RNG::UNIFORM, 0, 255);
69 Mat src(sz, CV_MAKE_TYPE(depth, srcCn), surfaceValue);
70
71 double sigmaC = rnd.uniform(1.0, 255.0);
72 int iterNum = int(rnd.uniform(1.0, 5.0));
73
74 Mat res;
75 rollingGuidanceFilter(src, res, -1, sigmaC, sigmaS, iterNum);
76
77 double normL1 = cvtest::norm(src, res, NORM_L1)/src.total()/src.channels();
78 EXPECT_LE(normL1, 1.0/64);
79 }
80 }
81
TEST_P(RollingGuidanceFilterTest,MultiThreadReproducibility)82 TEST_P(RollingGuidanceFilterTest, MultiThreadReproducibility)
83 {
84 if (cv::getNumberOfCPUs() == 1)
85 return;
86
87 RGFParams params = GetParam();
88 double sigmaS = get<0>(params);
89 int depth = get<1>(params);
90 int srcCn = get<2>(params);
91
92 double MAX_DIF = 1.0;
93 double MAX_MEAN_DIF = 1.0 / 64.0;
94 int loopsCount = 2;
95 RNG rnd(1);
96
97 Size sz(rnd.uniform(512,1024), rnd.uniform(512,1024));
98
99 Mat src(sz,CV_MAKE_TYPE(depth, srcCn));
100 if(src.depth()==CV_8U)
101 randu(src, 0, 255);
102 else if(src.depth()==CV_16S)
103 randu(src, -32767, 32767);
104 else
105 randu(src, -100000.0f, 100000.0f);
106
107 int nThreads = cv::getNumThreads();
108 if (nThreads == 1)
109 throw SkipTestException("Single thread environment");
110 for (int iter = 0; iter <= loopsCount; iter++)
111 {
112 int iterNum = int(rnd.uniform(1.0, 5.0));
113 double sigmaC = rnd.uniform(1.0, 255.0);
114
115 cv::setNumThreads(nThreads);
116 Mat resMultiThread;
117 rollingGuidanceFilter(src, resMultiThread, -1, sigmaC, sigmaS, iterNum);
118
119 cv::setNumThreads(1);
120 Mat resSingleThread;
121 rollingGuidanceFilter(src, resSingleThread, -1, sigmaC, sigmaS, iterNum);
122
123 EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_INF), MAX_DIF);
124 EXPECT_LE(cv::norm(resSingleThread, resMultiThread, NORM_L1), MAX_MEAN_DIF*src.total()*src.channels());
125 }
126 }
127
128 INSTANTIATE_TEST_CASE_P(TypicalSet1, RollingGuidanceFilterTest,
129 Combine(
130 Values(2.0, 5.0),
131 Values(CV_8U, CV_32F),
132 Values(1, 3)
133 )
134 );
135
136 //////////////////////////////////////////////////////////////////////////
137 //////////////////////////////////////////////////////////////////////////
138
139 typedef tuple<double, string, int> RGFBFParam;
140 typedef TestWithParam<RGFBFParam> RollingGuidanceFilterTest_BilateralRef;
141
TEST_P(RollingGuidanceFilterTest_BilateralRef,Accuracy)142 TEST_P(RollingGuidanceFilterTest_BilateralRef, Accuracy)
143 {
144 RGFBFParam params = GetParam();
145 double sigmaS = get<0>(params);
146 string srcPath = get<1>(params);
147 int srcType = get<2>(params);
148
149 Mat src = imread(getOpenCVExtraDir() + srcPath);
150 ASSERT_TRUE(!src.empty());
151 src = convertTypeAndSize(src, srcType, src.size());
152
153 RNG rnd(0);
154 double sigmaC = rnd.uniform(0.0, 255.0);
155
156 Mat resRef;
157 bilateralFilter(src, resRef, 0, sigmaC, sigmaS);
158
159 Mat res, joint = src.clone();
160 rollingGuidanceFilter(src, res, 0, sigmaC, sigmaS, 1);
161
162 checkSimilarity(res, resRef);
163 }
164
165 INSTANTIATE_TEST_CASE_P(TypicalSet2, RollingGuidanceFilterTest_BilateralRef,
166 Combine(
167 Values(4.0, 6.0, 8.0),
168 Values("/cv/shared/pic2.png", "/cv/shared/lena.png", "cv/shared/box_in_scene.png"),
169 Values(CV_8UC1, CV_8UC3, CV_32FC1, CV_32FC3)
170 )
171 );
172
173
174 }} // namespace
175