Merge pull request #2468 from mlyashko:back_proj_fix
[profile/ivi/opencv.git] / modules / cudaimgproc / perf / perf_hough.cpp
1 /*M///////////////////////////////////////////////////////////////////////////////////////
2 //
3 //  IMPORTANT: READ BEFORE DOWNLOADING, COPYING, INSTALLING OR USING.
4 //
5 //  By downloading, copying, installing or using the software you agree to this license.
6 //  If you do not agree to this license, do not download, install,
7 //  copy or use the software.
8 //
9 //
10 //                           License Agreement
11 //                For Open Source Computer Vision Library
12 //
13 // Copyright (C) 2000-2008, Intel Corporation, all rights reserved.
14 // Copyright (C) 2009, Willow Garage Inc., all rights reserved.
15 // Third party copyrights are property of their respective owners.
16 //
17 // Redistribution and use in source and binary forms, with or without modification,
18 // are permitted provided that the following conditions are met:
19 //
20 //   * Redistribution's of source code must retain the above copyright notice,
21 //     this list of conditions and the following disclaimer.
22 //
23 //   * Redistribution's in binary form must reproduce the above copyright notice,
24 //     this list of conditions and the following disclaimer in the documentation
25 //     and/or other materials provided with the distribution.
26 //
27 //   * The name of the copyright holders may not be used to endorse or promote products
28 //     derived from this software without specific prior written permission.
29 //
30 // This software is provided by the copyright holders and contributors "as is" and
31 // any express or implied warranties, including, but not limited to, the implied
32 // warranties of merchantability and fitness for a particular purpose are disclaimed.
33 // In no event shall the Intel Corporation or contributors be liable for any direct,
34 // indirect, incidental, special, exemplary, or consequential damages
35 // (including, but not limited to, procurement of substitute goods or services;
36 // loss of use, data, or profits; or business interruption) however caused
37 // and on any theory of liability, whether in contract, strict liability,
38 // or tort (including negligence or otherwise) arising in any way out of
39 // the use of this software, even if advised of the possibility of such damage.
40 //
41 //M*/
42
43 #include "perf_precomp.hpp"
44
45 using namespace std;
46 using namespace testing;
47 using namespace perf;
48
49 //////////////////////////////////////////////////////////////////////
50 // HoughLines
51
52 namespace
53 {
54     struct Vec4iComparator
55     {
56         bool operator()(const cv::Vec4i& a, const cv::Vec4i b) const
57         {
58             if (a[0] != b[0]) return a[0] < b[0];
59             else if(a[1] != b[1]) return a[1] < b[1];
60             else if(a[2] != b[2]) return a[2] < b[2];
61             else return a[3] < b[3];
62         }
63     };
64     struct Vec3fComparator
65     {
66         bool operator()(const cv::Vec3f& a, const cv::Vec3f b) const
67         {
68             if(a[0] != b[0]) return a[0] < b[0];
69             else if(a[1] != b[1]) return a[1] < b[1];
70             else return a[2] < b[2];
71         }
72     };
73     struct Vec2fComparator
74     {
75         bool operator()(const cv::Vec2f& a, const cv::Vec2f b) const
76         {
77             if(a[0] != b[0]) return a[0] < b[0];
78             else return a[1] < b[1];
79         }
80     };
81 }
82
83 PERF_TEST_P(Sz, HoughLines,
84             CUDA_TYPICAL_MAT_SIZES)
85 {
86     declare.time(30.0);
87
88     const cv::Size size = GetParam();
89
90     const float rho = 1.0f;
91     const float theta = static_cast<float>(CV_PI / 180.0);
92     const int threshold = 300;
93
94     cv::Mat src(size, CV_8UC1, cv::Scalar::all(0));
95     cv::line(src, cv::Point(0, 100), cv::Point(src.cols, 100), cv::Scalar::all(255), 1);
96     cv::line(src, cv::Point(0, 200), cv::Point(src.cols, 200), cv::Scalar::all(255), 1);
97     cv::line(src, cv::Point(0, 400), cv::Point(src.cols, 400), cv::Scalar::all(255), 1);
98     cv::line(src, cv::Point(100, 0), cv::Point(100, src.rows), cv::Scalar::all(255), 1);
99     cv::line(src, cv::Point(200, 0), cv::Point(200, src.rows), cv::Scalar::all(255), 1);
100     cv::line(src, cv::Point(400, 0), cv::Point(400, src.rows), cv::Scalar::all(255), 1);
101
102     if (PERF_RUN_CUDA())
103     {
104         const cv::cuda::GpuMat d_src(src);
105         cv::cuda::GpuMat d_lines;
106
107         cv::Ptr<cv::cuda::HoughLinesDetector> hough = cv::cuda::createHoughLinesDetector(rho, theta, threshold);
108
109         TEST_CYCLE() hough->detect(d_src, d_lines);
110
111         cv::Mat gpu_lines(d_lines.row(0));
112         cv::Vec2f* begin = gpu_lines.ptr<cv::Vec2f>(0);
113         cv::Vec2f* end = begin + gpu_lines.cols;
114         std::sort(begin, end, Vec2fComparator());
115         SANITY_CHECK(gpu_lines);
116     }
117     else
118     {
119         std::vector<cv::Vec2f> cpu_lines;
120
121         TEST_CYCLE() cv::HoughLines(src, cpu_lines, rho, theta, threshold);
122
123         SANITY_CHECK(cpu_lines);
124     }
125 }
126
127 //////////////////////////////////////////////////////////////////////
128 // HoughLinesP
129
130 DEF_PARAM_TEST_1(Image, std::string);
131
132 PERF_TEST_P(Image, HoughLinesP,
133             testing::Values("cv/shared/pic5.png", "stitching/a1.png"))
134 {
135     declare.time(30.0);
136
137     const std::string fileName = getDataPath(GetParam());
138
139     const float rho = 1.0f;
140     const float theta = static_cast<float>(CV_PI / 180.0);
141     const int threshold = 100;
142     const int minLineLength = 50;
143     const int maxLineGap = 5;
144
145     const cv::Mat image = cv::imread(fileName, cv::IMREAD_GRAYSCALE);
146     ASSERT_FALSE(image.empty());
147
148     cv::Mat mask;
149     cv::Canny(image, mask, 50, 100);
150
151     if (PERF_RUN_CUDA())
152     {
153         const cv::cuda::GpuMat d_mask(mask);
154         cv::cuda::GpuMat d_lines;
155
156         cv::Ptr<cv::cuda::HoughSegmentDetector> hough = cv::cuda::createHoughSegmentDetector(rho, theta, minLineLength, maxLineGap);
157
158         TEST_CYCLE() hough->detect(d_mask, d_lines);
159
160         cv::Mat gpu_lines(d_lines);
161         cv::Vec4i* begin = gpu_lines.ptr<cv::Vec4i>();
162         cv::Vec4i* end = begin + gpu_lines.cols;
163         std::sort(begin, end, Vec4iComparator());
164         SANITY_CHECK(gpu_lines);
165     }
166     else
167     {
168         std::vector<cv::Vec4i> cpu_lines;
169
170         TEST_CYCLE() cv::HoughLinesP(mask, cpu_lines, rho, theta, threshold, minLineLength, maxLineGap);
171
172         SANITY_CHECK(cpu_lines);
173     }
174 }
175
176 //////////////////////////////////////////////////////////////////////
177 // HoughCircles
178
179 DEF_PARAM_TEST(Sz_Dp_MinDist, cv::Size, float, float);
180
181 PERF_TEST_P(Sz_Dp_MinDist, HoughCircles,
182             Combine(CUDA_TYPICAL_MAT_SIZES,
183                     Values(1.0f, 2.0f, 4.0f),
184                     Values(1.0f)))
185 {
186     declare.time(30.0);
187
188     const cv::Size size = GET_PARAM(0);
189     const float dp = GET_PARAM(1);
190     const float minDist = GET_PARAM(2);
191
192     const int minRadius = 10;
193     const int maxRadius = 30;
194     const int cannyThreshold = 100;
195     const int votesThreshold = 15;
196
197     cv::Mat src(size, CV_8UC1, cv::Scalar::all(0));
198     cv::circle(src, cv::Point(100, 100), 20, cv::Scalar::all(255), -1);
199     cv::circle(src, cv::Point(200, 200), 25, cv::Scalar::all(255), -1);
200     cv::circle(src, cv::Point(200, 100), 25, cv::Scalar::all(255), -1);
201
202     if (PERF_RUN_CUDA())
203     {
204         const cv::cuda::GpuMat d_src(src);
205         cv::cuda::GpuMat d_circles;
206
207         cv::Ptr<cv::cuda::HoughCirclesDetector> houghCircles = cv::cuda::createHoughCirclesDetector(dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius);
208
209         TEST_CYCLE() houghCircles->detect(d_src, d_circles);
210
211         cv::Mat gpu_circles(d_circles);
212         cv::Vec3f* begin = gpu_circles.ptr<cv::Vec3f>(0);
213         cv::Vec3f* end = begin + gpu_circles.cols;
214         std::sort(begin, end, Vec3fComparator());
215         SANITY_CHECK(gpu_circles);
216     }
217     else
218     {
219         std::vector<cv::Vec3f> cpu_circles;
220
221         TEST_CYCLE() cv::HoughCircles(src, cpu_circles, cv::HOUGH_GRADIENT, dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius);
222
223         SANITY_CHECK(cpu_circles);
224     }
225 }
226
227 //////////////////////////////////////////////////////////////////////
228 // GeneralizedHough
229
230 PERF_TEST_P(Sz, GeneralizedHoughBallard, CUDA_TYPICAL_MAT_SIZES)
231 {
232     declare.time(10);
233
234     const cv::Size imageSize = GetParam();
235
236     const cv::Mat templ = readImage("cv/shared/templ.png", cv::IMREAD_GRAYSCALE);
237     ASSERT_FALSE(templ.empty());
238
239     cv::Mat image(imageSize, CV_8UC1, cv::Scalar::all(0));
240     templ.copyTo(image(cv::Rect(50, 50, templ.cols, templ.rows)));
241
242     cv::Mat edges;
243     cv::Canny(image, edges, 50, 100);
244
245     cv::Mat dx, dy;
246     cv::Sobel(image, dx, CV_32F, 1, 0);
247     cv::Sobel(image, dy, CV_32F, 0, 1);
248
249     if (PERF_RUN_CUDA())
250     {
251         cv::Ptr<cv::GeneralizedHoughBallard> alg = cv::cuda::createGeneralizedHoughBallard();
252
253         const cv::cuda::GpuMat d_edges(edges);
254         const cv::cuda::GpuMat d_dx(dx);
255         const cv::cuda::GpuMat d_dy(dy);
256         cv::cuda::GpuMat positions;
257
258         alg->setTemplate(cv::cuda::GpuMat(templ));
259
260         TEST_CYCLE() alg->detect(d_edges, d_dx, d_dy, positions);
261
262         CUDA_SANITY_CHECK(positions);
263     }
264     else
265     {
266         cv::Ptr<cv::GeneralizedHoughBallard> alg = cv::createGeneralizedHoughBallard();
267
268         cv::Mat positions;
269
270         alg->setTemplate(templ);
271
272         TEST_CYCLE() alg->detect(edges, dx, dy, positions);
273
274         CPU_SANITY_CHECK(positions);
275     }
276 }
277
278 PERF_TEST_P(Sz, GeneralizedHoughGuil, CUDA_TYPICAL_MAT_SIZES)
279 {
280     declare.time(10);
281
282     const cv::Size imageSize = GetParam();
283
284     const cv::Mat templ = readImage("cv/shared/templ.png", cv::IMREAD_GRAYSCALE);
285     ASSERT_FALSE(templ.empty());
286
287     cv::Mat image(imageSize, CV_8UC1, cv::Scalar::all(0));
288     templ.copyTo(image(cv::Rect(50, 50, templ.cols, templ.rows)));
289
290     cv::RNG rng(123456789);
291     const int objCount = rng.uniform(5, 15);
292     for (int i = 0; i < objCount; ++i)
293     {
294         double scale = rng.uniform(0.7, 1.3);
295         bool rotate = 1 == rng.uniform(0, 2);
296
297         cv::Mat obj;
298         cv::resize(templ, obj, cv::Size(), scale, scale);
299         if (rotate)
300             obj = obj.t();
301
302         cv::Point pos;
303
304         pos.x = rng.uniform(0, image.cols - obj.cols);
305         pos.y = rng.uniform(0, image.rows - obj.rows);
306
307         cv::Mat roi = image(cv::Rect(pos, obj.size()));
308         cv::add(roi, obj, roi);
309     }
310
311     cv::Mat edges;
312     cv::Canny(image, edges, 50, 100);
313
314     cv::Mat dx, dy;
315     cv::Sobel(image, dx, CV_32F, 1, 0);
316     cv::Sobel(image, dy, CV_32F, 0, 1);
317
318     if (PERF_RUN_CUDA())
319     {
320         cv::Ptr<cv::GeneralizedHoughGuil> alg = cv::cuda::createGeneralizedHoughGuil();
321         alg->setMaxAngle(90.0);
322         alg->setAngleStep(2.0);
323
324         const cv::cuda::GpuMat d_edges(edges);
325         const cv::cuda::GpuMat d_dx(dx);
326         const cv::cuda::GpuMat d_dy(dy);
327         cv::cuda::GpuMat positions;
328
329         alg->setTemplate(cv::cuda::GpuMat(templ));
330
331         TEST_CYCLE() alg->detect(d_edges, d_dx, d_dy, positions);
332
333         CUDA_SANITY_CHECK(positions);
334     }
335     else
336     {
337         cv::Ptr<cv::GeneralizedHoughGuil> alg = cv::createGeneralizedHoughGuil();
338         alg->setMaxAngle(90.0);
339         alg->setAngleStep(2.0);
340
341         cv::Mat positions;
342
343         alg->setTemplate(templ);
344
345         TEST_CYCLE() alg->detect(edges, dx, dy, positions);
346
347         CPU_SANITY_CHECK(positions);
348     }
349 }