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 "test_precomp.hpp" 44 45 #ifdef HAVE_CUDA 46 47 using namespace cvtest; 48 49 /////////////////////////////////////////////////////////////////////////////////////////////////////// 50 // HoughLines 51 52 PARAM_TEST_CASE(HoughLines, cv::cuda::DeviceInfo, cv::Size, UseRoi) 53 { 54 static void generateLines(cv::Mat& img) 55 { 56 img.setTo(cv::Scalar::all(0)); 57 58 cv::line(img, cv::Point(20, 0), cv::Point(20, img.rows), cv::Scalar::all(255)); 59 cv::line(img, cv::Point(0, 50), cv::Point(img.cols, 50), cv::Scalar::all(255)); 60 cv::line(img, cv::Point(0, 0), cv::Point(img.cols, img.rows), cv::Scalar::all(255)); 61 cv::line(img, cv::Point(img.cols, 0), cv::Point(0, img.rows), cv::Scalar::all(255)); 62 } 63 64 static void drawLines(cv::Mat& dst, const std::vector<cv::Vec2f>& lines) 65 { 66 dst.setTo(cv::Scalar::all(0)); 67 68 for (size_t i = 0; i < lines.size(); ++i) 69 { 70 float rho = lines[i][0], theta = lines[i][1]; 71 cv::Point pt1, pt2; 72 double a = std::cos(theta), b = std::sin(theta); 73 double x0 = a*rho, y0 = b*rho; 74 pt1.x = cvRound(x0 + 1000*(-b)); 75 pt1.y = cvRound(y0 + 1000*(a)); 76 pt2.x = cvRound(x0 - 1000*(-b)); 77 pt2.y = cvRound(y0 - 1000*(a)); 78 cv::line(dst, pt1, pt2, cv::Scalar::all(255)); 79 } 80 } 81 }; 82 83 CUDA_TEST_P(HoughLines, Accuracy) 84 { 85 const cv::cuda::DeviceInfo devInfo = GET_PARAM(0); 86 cv::cuda::setDevice(devInfo.deviceID()); 87 const cv::Size size = GET_PARAM(1); 88 const bool useRoi = GET_PARAM(2); 89 90 const float rho = 1.0f; 91 const float theta = (float) (1.5 * CV_PI / 180.0); 92 const int threshold = 100; 93 94 cv::Mat src(size, CV_8UC1); 95 generateLines(src); 96 97 cv::Ptr<cv::cuda::HoughLinesDetector> hough = cv::cuda::createHoughLinesDetector(rho, theta, threshold); 98 99 cv::cuda::GpuMat d_lines; 100 hough->detect(loadMat(src, useRoi), d_lines); 101 102 std::vector<cv::Vec2f> lines; 103 hough->downloadResults(d_lines, lines); 104 105 cv::Mat dst(size, CV_8UC1); 106 drawLines(dst, lines); 107 108 ASSERT_MAT_NEAR(src, dst, 0.0); 109 } 110 111 INSTANTIATE_TEST_CASE_P(CUDA_ImgProc, HoughLines, testing::Combine( 112 ALL_DEVICES, 113 DIFFERENT_SIZES, 114 WHOLE_SUBMAT)); 115 116 /////////////////////////////////////////////////////////////////////////////////////////////////////// 117 // HoughCircles 118 119 PARAM_TEST_CASE(HoughCircles, cv::cuda::DeviceInfo, cv::Size, UseRoi) 120 { 121 static void drawCircles(cv::Mat& dst, const std::vector<cv::Vec3f>& circles, bool fill) 122 { 123 dst.setTo(cv::Scalar::all(0)); 124 125 for (size_t i = 0; i < circles.size(); ++i) 126 cv::circle(dst, cv::Point2f(circles[i][0], circles[i][1]), (int)circles[i][2], cv::Scalar::all(255), fill ? -1 : 1); 127 } 128 }; 129 130 CUDA_TEST_P(HoughCircles, Accuracy) 131 { 132 const cv::cuda::DeviceInfo devInfo = GET_PARAM(0); 133 cv::cuda::setDevice(devInfo.deviceID()); 134 const cv::Size size = GET_PARAM(1); 135 const bool useRoi = GET_PARAM(2); 136 137 const float dp = 2.0f; 138 const float minDist = 0.0f; 139 const int minRadius = 10; 140 const int maxRadius = 20; 141 const int cannyThreshold = 100; 142 const int votesThreshold = 20; 143 144 std::vector<cv::Vec3f> circles_gold(4); 145 circles_gold[0] = cv::Vec3i(20, 20, minRadius); 146 circles_gold[1] = cv::Vec3i(90, 87, minRadius + 3); 147 circles_gold[2] = cv::Vec3i(30, 70, minRadius + 8); 148 circles_gold[3] = cv::Vec3i(80, 10, maxRadius); 149 150 cv::Mat src(size, CV_8UC1); 151 drawCircles(src, circles_gold, true); 152 153 cv::Ptr<cv::cuda::HoughCirclesDetector> houghCircles = cv::cuda::createHoughCirclesDetector(dp, minDist, cannyThreshold, votesThreshold, minRadius, maxRadius); 154 155 cv::cuda::GpuMat d_circles; 156 houghCircles->detect(loadMat(src, useRoi), d_circles); 157 158 std::vector<cv::Vec3f> circles; 159 d_circles.download(circles); 160 161 ASSERT_FALSE(circles.empty()); 162 163 for (size_t i = 0; i < circles.size(); ++i) 164 { 165 cv::Vec3f cur = circles[i]; 166 167 bool found = false; 168 169 for (size_t j = 0; j < circles_gold.size(); ++j) 170 { 171 cv::Vec3f gold = circles_gold[j]; 172 173 if (std::fabs(cur[0] - gold[0]) < 5 && std::fabs(cur[1] - gold[1]) < 5 && std::fabs(cur[2] - gold[2]) < 5) 174 { 175 found = true; 176 break; 177 } 178 } 179 180 ASSERT_TRUE(found); 181 } 182 } 183 184 INSTANTIATE_TEST_CASE_P(CUDA_ImgProc, HoughCircles, testing::Combine( 185 ALL_DEVICES, 186 DIFFERENT_SIZES, 187 WHOLE_SUBMAT)); 188 189 /////////////////////////////////////////////////////////////////////////////////////////////////////// 190 // GeneralizedHough 191 192 PARAM_TEST_CASE(GeneralizedHough, cv::cuda::DeviceInfo, UseRoi) 193 { 194 }; 195 196 CUDA_TEST_P(GeneralizedHough, Ballard) 197 { 198 const cv::cuda::DeviceInfo devInfo = GET_PARAM(0); 199 cv::cuda::setDevice(devInfo.deviceID()); 200 const bool useRoi = GET_PARAM(1); 201 202 cv::Mat templ = readImage("../cv/shared/templ.png", cv::IMREAD_GRAYSCALE); 203 ASSERT_FALSE(templ.empty()); 204 205 cv::Point templCenter(templ.cols / 2, templ.rows / 2); 206 207 const size_t gold_count = 3; 208 cv::Point pos_gold[gold_count]; 209 pos_gold[0] = cv::Point(templCenter.x + 10, templCenter.y + 10); 210 pos_gold[1] = cv::Point(2 * templCenter.x + 40, templCenter.y + 10); 211 pos_gold[2] = cv::Point(2 * templCenter.x + 40, 2 * templCenter.y + 40); 212 213 cv::Mat image(templ.rows * 3, templ.cols * 3, CV_8UC1, cv::Scalar::all(0)); 214 for (size_t i = 0; i < gold_count; ++i) 215 { 216 cv::Rect rec(pos_gold[i].x - templCenter.x, pos_gold[i].y - templCenter.y, templ.cols, templ.rows); 217 cv::Mat imageROI = image(rec); 218 templ.copyTo(imageROI); 219 } 220 221 cv::Ptr<cv::GeneralizedHoughBallard> alg = cv::cuda::createGeneralizedHoughBallard(); 222 alg->setVotesThreshold(200); 223 224 alg->setTemplate(loadMat(templ, useRoi)); 225 226 cv::cuda::GpuMat d_pos; 227 alg->detect(loadMat(image, useRoi), d_pos); 228 229 std::vector<cv::Vec4f> pos; 230 d_pos.download(pos); 231 232 ASSERT_EQ(gold_count, pos.size()); 233 234 for (size_t i = 0; i < gold_count; ++i) 235 { 236 cv::Point gold = pos_gold[i]; 237 238 bool found = false; 239 240 for (size_t j = 0; j < pos.size(); ++j) 241 { 242 cv::Point2f p(pos[j][0], pos[j][1]); 243 244 if (::fabs(p.x - gold.x) < 2 && ::fabs(p.y - gold.y) < 2) 245 { 246 found = true; 247 break; 248 } 249 } 250 251 ASSERT_TRUE(found); 252 } 253 } 254 255 INSTANTIATE_TEST_CASE_P(CUDA_ImgProc, GeneralizedHough, testing::Combine( 256 ALL_DEVICES, 257 WHOLE_SUBMAT)); 258 259 #endif // HAVE_CUDA 260