test_reductions.cpp 30 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121
  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. #include "test_precomp.hpp"
  43. #ifdef HAVE_CUDA
  44. namespace opencv_test { namespace {
  45. ////////////////////////////////////////////////////////////////////////////////
  46. // Norm
  47. PARAM_TEST_CASE(Norm, cv::cuda::DeviceInfo, cv::Size, MatDepth, NormCode, UseRoi)
  48. {
  49. cv::cuda::DeviceInfo devInfo;
  50. cv::Size size;
  51. int depth;
  52. int normCode;
  53. bool useRoi;
  54. virtual void SetUp()
  55. {
  56. devInfo = GET_PARAM(0);
  57. size = GET_PARAM(1);
  58. depth = GET_PARAM(2);
  59. normCode = GET_PARAM(3);
  60. useRoi = GET_PARAM(4);
  61. cv::cuda::setDevice(devInfo.deviceID());
  62. }
  63. };
  64. CUDA_TEST_P(Norm, Accuracy)
  65. {
  66. cv::Mat src = randomMat(size, depth);
  67. cv::Mat mask = randomMat(size, CV_8UC1, 0, 2);
  68. double val = cv::cuda::norm(loadMat(src, useRoi), normCode, loadMat(mask, useRoi));
  69. double val_gold = cv::norm(src, normCode, mask);
  70. EXPECT_NEAR(val_gold, val, depth < CV_32F ? 0.0 : 1.0);
  71. }
  72. CUDA_TEST_P(Norm, Async)
  73. {
  74. cv::Mat src = randomMat(size, depth);
  75. cv::Mat mask = randomMat(size, CV_8UC1, 0, 2);
  76. cv::cuda::Stream stream;
  77. cv::cuda::HostMem dst;
  78. cv::cuda::calcNorm(loadMat(src, useRoi), dst, normCode, loadMat(mask, useRoi), stream);
  79. stream.waitForCompletion();
  80. double val;
  81. dst.createMatHeader().convertTo(cv::Mat(1, 1, CV_64FC1, &val), CV_64F);
  82. double val_gold = cv::norm(src, normCode, mask);
  83. EXPECT_NEAR(val_gold, val, depth < CV_32F ? 0.0 : 1.0);
  84. }
  85. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Norm, testing::Combine(
  86. ALL_DEVICES,
  87. DIFFERENT_SIZES,
  88. testing::Values(MatDepth(CV_8U),
  89. MatDepth(CV_8S),
  90. MatDepth(CV_16U),
  91. MatDepth(CV_16S),
  92. MatDepth(CV_32S),
  93. MatDepth(CV_32F)),
  94. testing::Values(NormCode(cv::NORM_L1), NormCode(cv::NORM_L2), NormCode(cv::NORM_INF)),
  95. WHOLE_SUBMAT));
  96. ////////////////////////////////////////////////////////////////////////////////
  97. // normDiff
  98. PARAM_TEST_CASE(NormDiff, cv::cuda::DeviceInfo, cv::Size, NormCode, UseRoi)
  99. {
  100. cv::cuda::DeviceInfo devInfo;
  101. cv::Size size;
  102. int normCode;
  103. bool useRoi;
  104. virtual void SetUp()
  105. {
  106. devInfo = GET_PARAM(0);
  107. size = GET_PARAM(1);
  108. normCode = GET_PARAM(2);
  109. useRoi = GET_PARAM(3);
  110. cv::cuda::setDevice(devInfo.deviceID());
  111. }
  112. };
  113. CUDA_TEST_P(NormDiff, Accuracy)
  114. {
  115. cv::Mat src1 = randomMat(size, CV_8UC1);
  116. cv::Mat src2 = randomMat(size, CV_8UC1);
  117. double val = cv::cuda::norm(loadMat(src1, useRoi), loadMat(src2, useRoi), normCode);
  118. double val_gold = cv::norm(src1, src2, normCode);
  119. EXPECT_NEAR(val_gold, val, 0.0);
  120. }
  121. CUDA_TEST_P(NormDiff, Async)
  122. {
  123. cv::Mat src1 = randomMat(size, CV_8UC1);
  124. cv::Mat src2 = randomMat(size, CV_8UC1);
  125. cv::cuda::Stream stream;
  126. cv::cuda::HostMem dst;
  127. cv::cuda::calcNormDiff(loadMat(src1, useRoi), loadMat(src2, useRoi), dst, normCode, stream);
  128. stream.waitForCompletion();
  129. double val;
  130. const cv::Mat val_mat(1, 1, CV_64FC1, &val);
  131. dst.createMatHeader().convertTo(val_mat, CV_64F);
  132. double val_gold = cv::norm(src1, src2, normCode);
  133. EXPECT_NEAR(val_gold, val, 0.0);
  134. }
  135. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, NormDiff, testing::Combine(
  136. ALL_DEVICES,
  137. DIFFERENT_SIZES,
  138. testing::Values(NormCode(cv::NORM_L1), NormCode(cv::NORM_L2), NormCode(cv::NORM_INF)),
  139. WHOLE_SUBMAT));
  140. //////////////////////////////////////////////////////////////////////////////
  141. // Sum
  142. namespace
  143. {
  144. template <typename T>
  145. cv::Scalar absSumImpl(const cv::Mat& src)
  146. {
  147. const int cn = src.channels();
  148. cv::Scalar sum = cv::Scalar::all(0);
  149. for (int y = 0; y < src.rows; ++y)
  150. {
  151. for (int x = 0; x < src.cols; ++x)
  152. {
  153. for (int c = 0; c < cn; ++c)
  154. sum[c] += std::abs(src.at<T>(y, x * cn + c));
  155. }
  156. }
  157. return sum;
  158. }
  159. cv::Scalar absSumGold(const cv::Mat& src)
  160. {
  161. typedef cv::Scalar (*func_t)(const cv::Mat& src);
  162. static const func_t funcs[] =
  163. {
  164. absSumImpl<uchar>,
  165. absSumImpl<schar>,
  166. absSumImpl<ushort>,
  167. absSumImpl<short>,
  168. absSumImpl<int>,
  169. absSumImpl<float>,
  170. absSumImpl<double>
  171. };
  172. return funcs[src.depth()](src);
  173. }
  174. template <typename T>
  175. cv::Scalar sqrSumImpl(const cv::Mat& src)
  176. {
  177. const int cn = src.channels();
  178. cv::Scalar sum = cv::Scalar::all(0);
  179. for (int y = 0; y < src.rows; ++y)
  180. {
  181. for (int x = 0; x < src.cols; ++x)
  182. {
  183. for (int c = 0; c < cn; ++c)
  184. {
  185. const T val = src.at<T>(y, x * cn + c);
  186. sum[c] += val * val;
  187. }
  188. }
  189. }
  190. return sum;
  191. }
  192. cv::Scalar sqrSumGold(const cv::Mat& src)
  193. {
  194. typedef cv::Scalar (*func_t)(const cv::Mat& src);
  195. static const func_t funcs[] =
  196. {
  197. sqrSumImpl<uchar>,
  198. sqrSumImpl<schar>,
  199. sqrSumImpl<ushort>,
  200. sqrSumImpl<short>,
  201. sqrSumImpl<int>,
  202. sqrSumImpl<float>,
  203. sqrSumImpl<double>
  204. };
  205. return funcs[src.depth()](src);
  206. }
  207. }
  208. PARAM_TEST_CASE(Sum, cv::cuda::DeviceInfo, cv::Size, MatType, UseRoi)
  209. {
  210. cv::cuda::DeviceInfo devInfo;
  211. cv::Size size;
  212. int type;
  213. bool useRoi;
  214. cv::Mat src;
  215. virtual void SetUp()
  216. {
  217. devInfo = GET_PARAM(0);
  218. size = GET_PARAM(1);
  219. type = GET_PARAM(2);
  220. useRoi = GET_PARAM(3);
  221. cv::cuda::setDevice(devInfo.deviceID());
  222. src = randomMat(size, type, -128.0, 128.0);
  223. }
  224. };
  225. CUDA_TEST_P(Sum, Simple)
  226. {
  227. cv::Scalar val = cv::cuda::sum(loadMat(src, useRoi));
  228. cv::Scalar val_gold = cv::sum(src);
  229. EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
  230. }
  231. CUDA_TEST_P(Sum, Simple_Async)
  232. {
  233. cv::cuda::Stream stream;
  234. cv::cuda::HostMem dst;
  235. cv::cuda::calcSum(loadMat(src, useRoi), dst, cv::noArray(), stream);
  236. stream.waitForCompletion();
  237. cv::Scalar val;
  238. cv::Mat val_mat(dst.size(), CV_64FC(dst.channels()), val.val);
  239. dst.createMatHeader().convertTo(val_mat, CV_64F);
  240. cv::Scalar val_gold = cv::sum(src);
  241. EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
  242. }
  243. CUDA_TEST_P(Sum, Abs)
  244. {
  245. cv::Scalar val = cv::cuda::absSum(loadMat(src, useRoi));
  246. cv::Scalar val_gold = absSumGold(src);
  247. EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
  248. }
  249. CUDA_TEST_P(Sum, Abs_Async)
  250. {
  251. cv::cuda::Stream stream;
  252. cv::cuda::HostMem dst;
  253. cv::cuda::calcAbsSum(loadMat(src, useRoi), dst, cv::noArray(), stream);
  254. stream.waitForCompletion();
  255. cv::Scalar val;
  256. cv::Mat val_mat(dst.size(), CV_64FC(dst.channels()), val.val);
  257. dst.createMatHeader().convertTo(val_mat, CV_64F);
  258. cv::Scalar val_gold = absSumGold(src);
  259. EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
  260. }
  261. CUDA_TEST_P(Sum, Sqr)
  262. {
  263. cv::Scalar val = cv::cuda::sqrSum(loadMat(src, useRoi));
  264. cv::Scalar val_gold = sqrSumGold(src);
  265. EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
  266. }
  267. CUDA_TEST_P(Sum, Sqr_Async)
  268. {
  269. cv::cuda::Stream stream;
  270. cv::cuda::HostMem dst;
  271. cv::cuda::calcSqrSum(loadMat(src, useRoi), dst, cv::noArray(), stream);
  272. stream.waitForCompletion();
  273. cv::Scalar val;
  274. cv::Mat val_mat(dst.size(), CV_64FC(dst.channels()), val.val);
  275. dst.createMatHeader().convertTo(val_mat, CV_64F);
  276. cv::Scalar val_gold = sqrSumGold(src);
  277. EXPECT_SCALAR_NEAR(val_gold, val, CV_MAT_DEPTH(type) < CV_32F ? 0.0 : 0.5);
  278. }
  279. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Sum, testing::Combine(
  280. ALL_DEVICES,
  281. DIFFERENT_SIZES,
  282. TYPES(CV_8U, CV_64F, 1, 4),
  283. WHOLE_SUBMAT));
  284. ////////////////////////////////////////////////////////////////////////////////
  285. // MinMax
  286. PARAM_TEST_CASE(MinMax, cv::cuda::DeviceInfo, cv::Size, MatDepth, UseRoi)
  287. {
  288. cv::cuda::DeviceInfo devInfo;
  289. cv::Size size;
  290. int depth;
  291. bool useRoi;
  292. virtual void SetUp()
  293. {
  294. devInfo = GET_PARAM(0);
  295. size = GET_PARAM(1);
  296. depth = GET_PARAM(2);
  297. useRoi = GET_PARAM(3);
  298. cv::cuda::setDevice(devInfo.deviceID());
  299. }
  300. };
  301. CUDA_TEST_P(MinMax, WithoutMask)
  302. {
  303. cv::Mat src = randomMat(size, depth);
  304. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  305. {
  306. try
  307. {
  308. double minVal, maxVal;
  309. cv::cuda::minMax(loadMat(src), &minVal, &maxVal);
  310. }
  311. catch (const cv::Exception& e)
  312. {
  313. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  314. }
  315. }
  316. else
  317. {
  318. double minVal, maxVal;
  319. cv::cuda::minMax(loadMat(src, useRoi), &minVal, &maxVal);
  320. double minVal_gold, maxVal_gold;
  321. minMaxLocGold(src, &minVal_gold, &maxVal_gold);
  322. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  323. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  324. }
  325. }
  326. CUDA_TEST_P(MinMax, Async)
  327. {
  328. cv::Mat src = randomMat(size, depth);
  329. cv::cuda::Stream stream;
  330. cv::cuda::HostMem dst;
  331. cv::cuda::findMinMax(loadMat(src, useRoi), dst, cv::noArray(), stream);
  332. stream.waitForCompletion();
  333. double vals[2];
  334. const cv::Mat vals_mat(1, 2, CV_64FC1, &vals[0]);
  335. dst.createMatHeader().convertTo(vals_mat, CV_64F);
  336. double minVal_gold, maxVal_gold;
  337. minMaxLocGold(src, &minVal_gold, &maxVal_gold);
  338. EXPECT_DOUBLE_EQ(minVal_gold, vals[0]);
  339. EXPECT_DOUBLE_EQ(maxVal_gold, vals[1]);
  340. }
  341. CUDA_TEST_P(MinMax, WithMask)
  342. {
  343. cv::Mat src = randomMat(size, depth);
  344. cv::Mat mask = randomMat(size, CV_8UC1, 0.0, 2.0);
  345. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  346. {
  347. try
  348. {
  349. double minVal, maxVal;
  350. cv::cuda::minMax(loadMat(src), &minVal, &maxVal, loadMat(mask));
  351. }
  352. catch (const cv::Exception& e)
  353. {
  354. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  355. }
  356. }
  357. else
  358. {
  359. double minVal, maxVal;
  360. cv::cuda::minMax(loadMat(src, useRoi), &minVal, &maxVal, loadMat(mask, useRoi));
  361. double minVal_gold, maxVal_gold;
  362. minMaxLocGold(src, &minVal_gold, &maxVal_gold, 0, 0, mask);
  363. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  364. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  365. }
  366. }
  367. CUDA_TEST_P(MinMax, NullPtr)
  368. {
  369. cv::Mat src = randomMat(size, depth);
  370. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  371. {
  372. try
  373. {
  374. double minVal, maxVal;
  375. cv::cuda::minMax(loadMat(src), &minVal, 0);
  376. cv::cuda::minMax(loadMat(src), 0, &maxVal);
  377. }
  378. catch (const cv::Exception& e)
  379. {
  380. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  381. }
  382. }
  383. else
  384. {
  385. double minVal, maxVal;
  386. cv::cuda::minMax(loadMat(src, useRoi), &minVal, 0);
  387. cv::cuda::minMax(loadMat(src, useRoi), 0, &maxVal);
  388. double minVal_gold, maxVal_gold;
  389. minMaxLocGold(src, &minVal_gold, &maxVal_gold, 0, 0);
  390. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  391. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  392. }
  393. }
  394. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, MinMax, testing::Combine(
  395. ALL_DEVICES,
  396. DIFFERENT_SIZES,
  397. ALL_DEPTH,
  398. WHOLE_SUBMAT));
  399. ////////////////////////////////////////////////////////////////////////////////
  400. // MinMaxLoc
  401. namespace
  402. {
  403. template <typename T>
  404. void expectEqualImpl(const cv::Mat& src, cv::Point loc_gold, cv::Point loc)
  405. {
  406. EXPECT_EQ(src.at<T>(loc_gold.y, loc_gold.x), src.at<T>(loc.y, loc.x));
  407. }
  408. void expectEqual(const cv::Mat& src, cv::Point loc_gold, cv::Point loc)
  409. {
  410. typedef void (*func_t)(const cv::Mat& src, cv::Point loc_gold, cv::Point loc);
  411. static const func_t funcs[] =
  412. {
  413. expectEqualImpl<uchar>,
  414. expectEqualImpl<schar>,
  415. expectEqualImpl<ushort>,
  416. expectEqualImpl<short>,
  417. expectEqualImpl<int>,
  418. expectEqualImpl<float>,
  419. expectEqualImpl<double>
  420. };
  421. funcs[src.depth()](src, loc_gold, loc);
  422. }
  423. }
  424. PARAM_TEST_CASE(MinMaxLoc, cv::cuda::DeviceInfo, cv::Size, MatDepth, UseRoi)
  425. {
  426. cv::cuda::DeviceInfo devInfo;
  427. cv::Size size;
  428. int depth;
  429. bool useRoi;
  430. virtual void SetUp()
  431. {
  432. devInfo = GET_PARAM(0);
  433. size = GET_PARAM(1);
  434. depth = GET_PARAM(2);
  435. useRoi = GET_PARAM(3);
  436. cv::cuda::setDevice(devInfo.deviceID());
  437. }
  438. };
  439. CUDA_TEST_P(MinMaxLoc, WithoutMask)
  440. {
  441. cv::Mat src = randomMat(size, depth);
  442. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  443. {
  444. try
  445. {
  446. double minVal, maxVal;
  447. cv::Point minLoc, maxLoc;
  448. cv::cuda::minMaxLoc(loadMat(src), &minVal, &maxVal, &minLoc, &maxLoc);
  449. }
  450. catch (const cv::Exception& e)
  451. {
  452. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  453. }
  454. }
  455. else
  456. {
  457. double minVal, maxVal;
  458. cv::Point minLoc, maxLoc;
  459. cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc);
  460. double minVal_gold, maxVal_gold;
  461. cv::Point minLoc_gold, maxLoc_gold;
  462. minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
  463. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  464. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  465. expectEqual(src, minLoc_gold, minLoc);
  466. expectEqual(src, maxLoc_gold, maxLoc);
  467. }
  468. }
  469. CUDA_TEST_P(MinMaxLoc, OneRowMat)
  470. {
  471. cv::Mat src = randomMat(cv::Size(size.width, 1), depth);
  472. double minVal, maxVal;
  473. cv::Point minLoc, maxLoc;
  474. cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc);
  475. double minVal_gold, maxVal_gold;
  476. cv::Point minLoc_gold, maxLoc_gold;
  477. minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
  478. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  479. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  480. expectEqual(src, minLoc_gold, minLoc);
  481. expectEqual(src, maxLoc_gold, maxLoc);
  482. }
  483. CUDA_TEST_P(MinMaxLoc, OneColumnMat)
  484. {
  485. cv::Mat src = randomMat(cv::Size(1, size.height), depth);
  486. double minVal, maxVal;
  487. cv::Point minLoc, maxLoc;
  488. cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc);
  489. double minVal_gold, maxVal_gold;
  490. cv::Point minLoc_gold, maxLoc_gold;
  491. minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
  492. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  493. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  494. expectEqual(src, minLoc_gold, minLoc);
  495. expectEqual(src, maxLoc_gold, maxLoc);
  496. }
  497. CUDA_TEST_P(MinMaxLoc, Async)
  498. {
  499. cv::Mat src = randomMat(size, depth);
  500. cv::cuda::Stream stream;
  501. cv::cuda::HostMem minMaxVals, locVals;
  502. cv::cuda::findMinMaxLoc(loadMat(src, useRoi), minMaxVals, locVals, cv::noArray(), stream);
  503. stream.waitForCompletion();
  504. double vals[2];
  505. const cv::Mat vals_mat(2, 1, CV_64FC1, &vals[0]);
  506. minMaxVals.createMatHeader().convertTo(vals_mat, CV_64F);
  507. int locs[2];
  508. const cv::Mat locs_mat(2, 1, CV_32SC1, &locs[0]);
  509. locVals.createMatHeader().copyTo(locs_mat);
  510. cv::Point locs2D[] = {
  511. cv::Point(locs[0] % src.cols, locs[0] / src.cols),
  512. cv::Point(locs[1] % src.cols, locs[1] / src.cols),
  513. };
  514. double minVal_gold, maxVal_gold;
  515. cv::Point minLoc_gold, maxLoc_gold;
  516. minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
  517. EXPECT_DOUBLE_EQ(minVal_gold, vals[0]);
  518. EXPECT_DOUBLE_EQ(maxVal_gold, vals[1]);
  519. expectEqual(src, minLoc_gold, locs2D[0]);
  520. expectEqual(src, maxLoc_gold, locs2D[1]);
  521. }
  522. CUDA_TEST_P(MinMaxLoc, WithMask)
  523. {
  524. cv::Mat src = randomMat(size, depth);
  525. cv::Mat mask = randomMat(size, CV_8UC1, 0.0, 2.0);
  526. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  527. {
  528. try
  529. {
  530. double minVal, maxVal;
  531. cv::Point minLoc, maxLoc;
  532. cv::cuda::minMaxLoc(loadMat(src), &minVal, &maxVal, &minLoc, &maxLoc, loadMat(mask));
  533. }
  534. catch (const cv::Exception& e)
  535. {
  536. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  537. }
  538. }
  539. else
  540. {
  541. double minVal, maxVal;
  542. cv::Point minLoc, maxLoc;
  543. cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, &maxVal, &minLoc, &maxLoc, loadMat(mask, useRoi));
  544. double minVal_gold, maxVal_gold;
  545. cv::Point minLoc_gold, maxLoc_gold;
  546. minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold, mask);
  547. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  548. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  549. expectEqual(src, minLoc_gold, minLoc);
  550. expectEqual(src, maxLoc_gold, maxLoc);
  551. }
  552. }
  553. CUDA_TEST_P(MinMaxLoc, NullPtr)
  554. {
  555. cv::Mat src = randomMat(size, depth);
  556. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  557. {
  558. try
  559. {
  560. double minVal, maxVal;
  561. cv::Point minLoc, maxLoc;
  562. cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, 0, 0, 0);
  563. cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, &maxVal, 0, 0);
  564. cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, &minLoc, 0);
  565. cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, 0, &maxLoc);
  566. }
  567. catch (const cv::Exception& e)
  568. {
  569. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  570. }
  571. }
  572. else
  573. {
  574. double minVal, maxVal;
  575. cv::Point minLoc, maxLoc;
  576. cv::cuda::minMaxLoc(loadMat(src, useRoi), &minVal, 0, 0, 0);
  577. cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, &maxVal, 0, 0);
  578. cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, &minLoc, 0);
  579. cv::cuda::minMaxLoc(loadMat(src, useRoi), 0, 0, 0, &maxLoc);
  580. double minVal_gold, maxVal_gold;
  581. cv::Point minLoc_gold, maxLoc_gold;
  582. minMaxLocGold(src, &minVal_gold, &maxVal_gold, &minLoc_gold, &maxLoc_gold);
  583. EXPECT_DOUBLE_EQ(minVal_gold, minVal);
  584. EXPECT_DOUBLE_EQ(maxVal_gold, maxVal);
  585. expectEqual(src, minLoc_gold, minLoc);
  586. expectEqual(src, maxLoc_gold, maxLoc);
  587. }
  588. }
  589. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, MinMaxLoc, testing::Combine(
  590. ALL_DEVICES,
  591. DIFFERENT_SIZES,
  592. ALL_DEPTH,
  593. WHOLE_SUBMAT));
  594. ////////////////////////////////////////////////////////////////////////////
  595. // CountNonZero
  596. PARAM_TEST_CASE(CountNonZero, cv::cuda::DeviceInfo, cv::Size, MatDepth, UseRoi)
  597. {
  598. cv::cuda::DeviceInfo devInfo;
  599. cv::Size size;
  600. int depth;
  601. bool useRoi;
  602. cv::Mat src;
  603. virtual void SetUp()
  604. {
  605. devInfo = GET_PARAM(0);
  606. size = GET_PARAM(1);
  607. depth = GET_PARAM(2);
  608. useRoi = GET_PARAM(3);
  609. cv::cuda::setDevice(devInfo.deviceID());
  610. cv::Mat srcBase = randomMat(size, CV_8U, 0.0, 1.5);
  611. srcBase.convertTo(src, depth);
  612. }
  613. };
  614. CUDA_TEST_P(CountNonZero, Accuracy)
  615. {
  616. if (depth == CV_64F && !supportFeature(devInfo, cv::cuda::NATIVE_DOUBLE))
  617. {
  618. try
  619. {
  620. cv::cuda::countNonZero(loadMat(src));
  621. }
  622. catch (const cv::Exception& e)
  623. {
  624. ASSERT_EQ(cv::Error::StsUnsupportedFormat, e.code);
  625. }
  626. }
  627. else
  628. {
  629. int val = cv::cuda::countNonZero(loadMat(src, useRoi));
  630. int val_gold = cv::countNonZero(src);
  631. ASSERT_EQ(val_gold, val);
  632. }
  633. }
  634. CUDA_TEST_P(CountNonZero, Async)
  635. {
  636. cv::cuda::Stream stream;
  637. cv::cuda::HostMem dst;
  638. cv::cuda::countNonZero(loadMat(src, useRoi), dst, stream);
  639. stream.waitForCompletion();
  640. int val;
  641. const cv::Mat val_mat(1, 1, CV_32SC1, &val);
  642. dst.createMatHeader().copyTo(val_mat);
  643. int val_gold = cv::countNonZero(src);
  644. ASSERT_EQ(val_gold, val);
  645. }
  646. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, CountNonZero, testing::Combine(
  647. ALL_DEVICES,
  648. DIFFERENT_SIZES,
  649. ALL_DEPTH,
  650. WHOLE_SUBMAT));
  651. //////////////////////////////////////////////////////////////////////////////
  652. // Reduce
  653. CV_ENUM(ReduceCode, cv::REDUCE_SUM, cv::REDUCE_AVG, cv::REDUCE_MAX, cv::REDUCE_MIN)
  654. #define ALL_REDUCE_CODES testing::Values(ReduceCode(cv::REDUCE_SUM), ReduceCode(cv::REDUCE_AVG), ReduceCode(cv::REDUCE_MAX), ReduceCode(cv::REDUCE_MIN))
  655. PARAM_TEST_CASE(Reduce, cv::cuda::DeviceInfo, cv::Size, MatDepth, Channels, ReduceCode, UseRoi)
  656. {
  657. cv::cuda::DeviceInfo devInfo;
  658. cv::Size size;
  659. int depth;
  660. int channels;
  661. int reduceOp;
  662. bool useRoi;
  663. int type;
  664. int dst_depth;
  665. int dst_type;
  666. virtual void SetUp()
  667. {
  668. devInfo = GET_PARAM(0);
  669. size = GET_PARAM(1);
  670. depth = GET_PARAM(2);
  671. channels = GET_PARAM(3);
  672. reduceOp = GET_PARAM(4);
  673. useRoi = GET_PARAM(5);
  674. cv::cuda::setDevice(devInfo.deviceID());
  675. type = CV_MAKE_TYPE(depth, channels);
  676. if (reduceOp == cv::REDUCE_MAX || reduceOp == cv::REDUCE_MIN)
  677. dst_depth = depth;
  678. else if (reduceOp == cv::REDUCE_SUM)
  679. dst_depth = depth == CV_8U ? CV_32S : depth < CV_64F ? CV_32F : depth;
  680. else
  681. dst_depth = depth < CV_32F ? CV_32F : depth;
  682. dst_type = CV_MAKE_TYPE(dst_depth, channels);
  683. }
  684. };
  685. CUDA_TEST_P(Reduce, Rows)
  686. {
  687. cv::Mat src = randomMat(size, type);
  688. cv::cuda::GpuMat dst = createMat(cv::Size(src.cols, 1), dst_type, useRoi);
  689. cv::cuda::reduce(loadMat(src, useRoi), dst, 0, reduceOp, dst_depth);
  690. cv::Mat dst_gold;
  691. cv::reduce(src, dst_gold, 0, reduceOp, dst_depth);
  692. EXPECT_MAT_NEAR(dst_gold, dst, dst_depth < CV_32F ? 0.0 : 0.02);
  693. }
  694. CUDA_TEST_P(Reduce, Cols)
  695. {
  696. cv::Mat src = randomMat(size, type);
  697. cv::cuda::GpuMat dst;
  698. cv::cuda::reduce(loadMat(src, useRoi), dst, 1, reduceOp, dst_depth);
  699. cv::Mat dst_gold;
  700. cv::reduce(src, dst_gold, 1, reduceOp, dst_depth);
  701. EXPECT_MAT_NEAR(dst_gold, dst, dst_depth < CV_32F ? 0.0 : 0.02);
  702. }
  703. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Reduce, testing::Combine(
  704. ALL_DEVICES,
  705. DIFFERENT_SIZES,
  706. testing::Values(MatDepth(CV_8U),
  707. MatDepth(CV_16U),
  708. MatDepth(CV_16S),
  709. MatDepth(CV_32F),
  710. MatDepth(CV_64F)),
  711. ALL_CHANNELS,
  712. ALL_REDUCE_CODES,
  713. WHOLE_SUBMAT));
  714. //////////////////////////////////////////////////////////////////////////////
  715. // Normalize
  716. PARAM_TEST_CASE(Normalize, cv::cuda::DeviceInfo, cv::Size, MatDepth, NormCode, UseRoi)
  717. {
  718. cv::cuda::DeviceInfo devInfo;
  719. cv::Size size;
  720. int type;
  721. int norm_type;
  722. bool useRoi;
  723. double alpha;
  724. double beta;
  725. virtual void SetUp()
  726. {
  727. devInfo = GET_PARAM(0);
  728. size = GET_PARAM(1);
  729. type = GET_PARAM(2);
  730. norm_type = GET_PARAM(3);
  731. useRoi = GET_PARAM(4);
  732. cv::cuda::setDevice(devInfo.deviceID());
  733. alpha = 1;
  734. beta = 0;
  735. }
  736. };
  737. CUDA_TEST_P(Normalize, WithOutMask)
  738. {
  739. cv::Mat src = randomMat(size, type);
  740. cv::cuda::GpuMat dst = createMat(size, type, useRoi);
  741. cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, type);
  742. cv::Mat dst_gold;
  743. cv::normalize(src, dst_gold, alpha, beta, norm_type, type);
  744. EXPECT_MAT_NEAR(dst_gold, dst, type < CV_32F ? 1.0 : 1e-4);
  745. }
  746. CUDA_TEST_P(Normalize, WithMask)
  747. {
  748. cv::Mat src = randomMat(size, type);
  749. cv::Mat mask = randomMat(size, CV_8UC1, 0, 2);
  750. cv::cuda::GpuMat dst = createMat(size, type, useRoi);
  751. dst.setTo(cv::Scalar::all(0));
  752. cv::cuda::normalize(loadMat(src, useRoi), dst, alpha, beta, norm_type, -1, loadMat(mask, useRoi));
  753. cv::Mat dst_gold(size, type);
  754. dst_gold.setTo(cv::Scalar::all(0));
  755. cv::normalize(src, dst_gold, alpha, beta, norm_type, -1, mask);
  756. EXPECT_MAT_NEAR(dst_gold, dst, type < CV_32F ? 1.0 : 1e-4);
  757. }
  758. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Normalize, testing::Combine(
  759. ALL_DEVICES,
  760. DIFFERENT_SIZES,
  761. ALL_DEPTH,
  762. testing::Values(NormCode(cv::NORM_L1), NormCode(cv::NORM_L2), NormCode(cv::NORM_INF), NormCode(cv::NORM_MINMAX)),
  763. WHOLE_SUBMAT));
  764. ////////////////////////////////////////////////////////////////////////////////
  765. // MeanStdDev
  766. PARAM_TEST_CASE(MeanStdDev, cv::cuda::DeviceInfo, cv::Size, UseRoi)
  767. {
  768. cv::cuda::DeviceInfo devInfo;
  769. cv::Size size;
  770. bool useRoi;
  771. virtual void SetUp()
  772. {
  773. devInfo = GET_PARAM(0);
  774. size = GET_PARAM(1);
  775. useRoi = GET_PARAM(2);
  776. cv::cuda::setDevice(devInfo.deviceID());
  777. }
  778. };
  779. CUDA_TEST_P(MeanStdDev, Accuracy)
  780. {
  781. cv::Mat src = randomMat(size, CV_8UC1);
  782. if (!supportFeature(devInfo, cv::cuda::FEATURE_SET_COMPUTE_13))
  783. {
  784. try
  785. {
  786. cv::Scalar mean;
  787. cv::Scalar stddev;
  788. cv::cuda::meanStdDev(loadMat(src, useRoi), mean, stddev);
  789. }
  790. catch (const cv::Exception& e)
  791. {
  792. ASSERT_EQ(cv::Error::StsNotImplemented, e.code);
  793. }
  794. }
  795. else
  796. {
  797. cv::Scalar mean;
  798. cv::Scalar stddev;
  799. cv::cuda::meanStdDev(loadMat(src, useRoi), mean, stddev);
  800. cv::Scalar mean_gold;
  801. cv::Scalar stddev_gold;
  802. cv::meanStdDev(src, mean_gold, stddev_gold);
  803. EXPECT_SCALAR_NEAR(mean_gold, mean, 1e-5);
  804. EXPECT_SCALAR_NEAR(stddev_gold, stddev, 1e-5);
  805. }
  806. }
  807. CUDA_TEST_P(MeanStdDev, Async)
  808. {
  809. cv::Mat src = randomMat(size, CV_8UC1);
  810. cv::cuda::Stream stream;
  811. cv::cuda::HostMem dst;
  812. cv::cuda::meanStdDev(loadMat(src, useRoi), dst, stream);
  813. stream.waitForCompletion();
  814. double vals[2];
  815. dst.createMatHeader().copyTo(cv::Mat(1, 2, CV_64FC1, &vals[0]));
  816. cv::Scalar mean_gold;
  817. cv::Scalar stddev_gold;
  818. cv::meanStdDev(src, mean_gold, stddev_gold);
  819. EXPECT_SCALAR_NEAR(mean_gold, cv::Scalar(vals[0]), 1e-5);
  820. EXPECT_SCALAR_NEAR(stddev_gold, cv::Scalar(vals[1]), 1e-5);
  821. }
  822. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, MeanStdDev, testing::Combine(
  823. ALL_DEVICES,
  824. DIFFERENT_SIZES,
  825. WHOLE_SUBMAT));
  826. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  827. // Integral
  828. PARAM_TEST_CASE(Integral, cv::cuda::DeviceInfo, cv::Size, UseRoi)
  829. {
  830. cv::cuda::DeviceInfo devInfo;
  831. cv::Size size;
  832. bool useRoi;
  833. virtual void SetUp()
  834. {
  835. devInfo = GET_PARAM(0);
  836. size = GET_PARAM(1);
  837. useRoi = GET_PARAM(2);
  838. cv::cuda::setDevice(devInfo.deviceID());
  839. }
  840. };
  841. CUDA_TEST_P(Integral, Accuracy)
  842. {
  843. cv::Mat src = randomMat(size, CV_8UC1);
  844. cv::cuda::GpuMat dst = createMat(cv::Size(src.cols + 1, src.rows + 1), CV_32SC1, useRoi);
  845. cv::cuda::integral(loadMat(src, useRoi), dst);
  846. cv::Mat dst_gold;
  847. cv::integral(src, dst_gold, CV_32S);
  848. EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
  849. }
  850. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, Integral, testing::Combine(
  851. ALL_DEVICES,
  852. testing::Values(cv::Size(16, 16), cv::Size(128, 128), cv::Size(113, 113), cv::Size(768, 1066)),
  853. WHOLE_SUBMAT));
  854. ///////////////////////////////////////////////////////////////////////////////////////////////////////
  855. // IntegralSqr
  856. PARAM_TEST_CASE(IntegralSqr, cv::cuda::DeviceInfo, cv::Size, UseRoi)
  857. {
  858. cv::cuda::DeviceInfo devInfo;
  859. cv::Size size;
  860. bool useRoi;
  861. virtual void SetUp()
  862. {
  863. devInfo = GET_PARAM(0);
  864. size = GET_PARAM(1);
  865. useRoi = GET_PARAM(2);
  866. cv::cuda::setDevice(devInfo.deviceID());
  867. }
  868. };
  869. CUDA_TEST_P(IntegralSqr, Accuracy)
  870. {
  871. cv::Mat src = randomMat(size, CV_8UC1);
  872. cv::cuda::GpuMat dst = createMat(cv::Size(src.cols + 1, src.rows + 1), CV_64FC1, useRoi);
  873. cv::cuda::sqrIntegral(loadMat(src, useRoi), dst);
  874. cv::Mat dst_gold, temp;
  875. cv::integral(src, temp, dst_gold);
  876. EXPECT_MAT_NEAR(dst_gold, dst, 0.0);
  877. }
  878. INSTANTIATE_TEST_CASE_P(CUDA_Arithm, IntegralSqr, testing::Combine(
  879. ALL_DEVICES,
  880. DIFFERENT_SIZES,
  881. WHOLE_SUBMAT));
  882. }} // namespace
  883. #endif // HAVE_CUDA