test_connectedcomponents.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479
  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. #ifdef HAVE_CUDA
  6. namespace opencv_test {
  7. namespace {
  8. // This function force a row major order for the labels
  9. template <typename LabelT>
  10. void normalize_labels_impl(Mat& labels) {
  11. std::map<LabelT, LabelT> map_new_labels;
  12. LabelT i_max_new_label = 0;
  13. for (int r = 0; r < labels.rows; ++r) {
  14. LabelT* const mat_row = labels.ptr<LabelT>(r);
  15. for (int c = 0; c < labels.cols; ++c) {
  16. LabelT iCurLabel = mat_row[c];
  17. if (iCurLabel > 0) {
  18. if (map_new_labels.find(iCurLabel) == map_new_labels.end()) {
  19. map_new_labels[iCurLabel] = ++i_max_new_label;
  20. }
  21. mat_row[c] = map_new_labels.at(iCurLabel);
  22. }
  23. }
  24. }
  25. }
  26. void normalize_labels(Mat& labels) {
  27. int type = labels.type();
  28. int depth = type & CV_MAT_DEPTH_MASK;
  29. int chans = 1 + (type >> CV_CN_SHIFT);
  30. CV_Assert(chans == 1);
  31. CV_Assert(depth == CV_16U || depth == CV_16S || depth == CV_32S);
  32. switch (depth) {
  33. case CV_16U: normalize_labels_impl<ushort>(labels); break;
  34. case CV_16S: normalize_labels_impl<short>(labels); break;
  35. case CV_32S: normalize_labels_impl<int>(labels); break;
  36. default: CV_Assert(0);
  37. }
  38. }
  39. ////////////////////////////////////////////////////////
  40. // ConnectedComponents
  41. PARAM_TEST_CASE(ConnectedComponents, cv::cuda::DeviceInfo, int, int, cv::cuda::ConnectedComponentsAlgorithmsTypes)
  42. {
  43. cv::cuda::DeviceInfo devInfo;
  44. int connectivity;
  45. int ltype;
  46. cv::cuda::ConnectedComponentsAlgorithmsTypes algo;
  47. virtual void SetUp()
  48. {
  49. devInfo = GET_PARAM(0);
  50. connectivity = GET_PARAM(1);
  51. ltype = GET_PARAM(2);
  52. algo = GET_PARAM(3);
  53. cv::cuda::setDevice(devInfo.deviceID());
  54. }
  55. };
  56. CUDA_TEST_P(ConnectedComponents, Chessboard_Even)
  57. {
  58. std::initializer_list<int> sizes{ 16, 16 };
  59. cv::Mat1b input;
  60. cv::Mat1i correct_output_int;
  61. cv::Mat correct_output;
  62. // Chessboard image with even number of rows and cols
  63. // Note that this is the maximum number of labels for 4-way connectivity
  64. {
  65. input = cv::Mat1b(sizes, {
  66. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  67. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  68. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  69. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  70. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  71. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  72. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  73. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  74. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  75. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  76. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  77. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  78. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  79. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  80. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  81. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
  82. });
  83. if (connectivity == 8) {
  84. correct_output_int = cv::Mat1i(sizes, {
  85. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  86. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  87. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  88. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  89. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  90. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  91. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  92. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  93. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  94. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  95. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  96. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  97. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  98. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  99. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  100. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
  101. });
  102. }
  103. else {
  104. correct_output_int = cv::Mat1i(sizes, {
  105. 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0,
  106. 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16,
  107. 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0,
  108. 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32,
  109. 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0,
  110. 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48,
  111. 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0,
  112. 0, 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64,
  113. 65, 0, 66, 0, 67, 0, 68, 0, 69, 0, 70, 0, 71, 0, 72, 0,
  114. 0, 73, 0, 74, 0, 75, 0, 76, 0, 77, 0, 78, 0, 79, 0, 80,
  115. 81, 0, 82, 0, 83, 0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0,
  116. 0, 89, 0, 90, 0, 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96,
  117. 97, 0, 98, 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0,
  118. 0, 105, 0, 106, 0, 107, 0, 108, 0, 109, 0, 110, 0, 111, 0, 112,
  119. 113, 0, 114, 0, 115, 0, 116, 0, 117, 0, 118, 0, 119, 0, 120, 0,
  120. 0, 121, 0, 122, 0, 123, 0, 124, 0, 125, 0, 126, 0, 127, 0, 128
  121. });
  122. }
  123. }
  124. correct_output_int.convertTo(correct_output, CV_MAT_DEPTH(ltype));
  125. cv::Mat labels;
  126. cv::Mat diff;
  127. cv::cuda::GpuMat d_input;
  128. cv::cuda::GpuMat d_labels;
  129. d_input.upload(input);
  130. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_input, d_labels, connectivity, ltype, algo));
  131. d_labels.download(labels);
  132. normalize_labels(labels);
  133. diff = labels != correct_output;
  134. EXPECT_EQ(cv::countNonZero(diff), 0);
  135. }
  136. CUDA_TEST_P(ConnectedComponents, Chessboard_Odd)
  137. {
  138. std::initializer_list<int> sizes{ 15, 15 };
  139. cv::Mat1b input;
  140. cv::Mat1i correct_output_int;
  141. cv::Mat correct_output;
  142. // Chessboard image with even number of rows and cols
  143. // Note that this is the maximum number of labels for 4-way connectivity
  144. {
  145. input = Mat1b(sizes, {
  146. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  147. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  148. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  149. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  150. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  151. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  152. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  153. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  154. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  155. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  156. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  157. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  158. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  159. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  160. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
  161. });
  162. if (connectivity == 8) {
  163. correct_output_int = Mat1i(sizes, {
  164. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  165. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  166. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  167. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  168. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  169. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  170. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  171. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  172. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  173. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  174. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  175. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  176. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  177. 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  178. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
  179. });
  180. }
  181. else {
  182. correct_output_int = Mat1i(sizes, {
  183. 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
  184. 0, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0,
  185. 16, 0, 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23,
  186. 0, 24, 0, 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0,
  187. 31, 0, 32, 0, 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38,
  188. 0, 39, 0, 40, 0, 41, 0, 42, 0, 43, 0, 44, 0, 45, 0,
  189. 46, 0, 47, 0, 48, 0, 49, 0, 50, 0, 51, 0, 52, 0, 53,
  190. 0, 54, 0, 55, 0, 56, 0, 57, 0, 58, 0, 59, 0, 60, 0,
  191. 61, 0, 62, 0, 63, 0, 64, 0, 65, 0, 66, 0, 67, 0, 68,
  192. 0, 69, 0, 70, 0, 71, 0, 72, 0, 73, 0, 74, 0, 75, 0,
  193. 76, 0, 77, 0, 78, 0, 79, 0, 80, 0, 81, 0, 82, 0, 83,
  194. 0, 84, 0, 85, 0, 86, 0, 87, 0, 88, 0, 89, 0, 90, 0,
  195. 91, 0, 92, 0, 93, 0, 94, 0, 95, 0, 96, 0, 97, 0, 98,
  196. 0, 99, 0, 100, 0, 101, 0, 102, 0, 103, 0, 104, 0, 105, 0,
  197. 106, 0, 107, 0, 108, 0, 109, 0, 110, 0, 111, 0, 112, 0, 113
  198. });
  199. }
  200. }
  201. correct_output_int.convertTo(correct_output, CV_MAT_DEPTH(ltype));
  202. cv::Mat labels;
  203. cv::Mat diff;
  204. cv::cuda::GpuMat d_input;
  205. cv::cuda::GpuMat d_labels;
  206. d_input.upload(input);
  207. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_input, d_labels, connectivity, ltype, algo));
  208. d_labels.download(labels);
  209. normalize_labels(labels);
  210. diff = labels != correct_output;
  211. EXPECT_EQ(cv::countNonZero(diff), 0);
  212. }
  213. CUDA_TEST_P(ConnectedComponents, Maxlabels_8conn_Even)
  214. {
  215. std::initializer_list<int> sizes{ 16, 16 };
  216. cv::Mat1b input;
  217. cv::Mat1i correct_output_int;
  218. cv::Mat correct_output;
  219. // Chessboard image with even number of rows and cols
  220. // Note that this is the maximum number of labels for 4-way connectivity
  221. {
  222. input = Mat1b(sizes, {
  223. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  224. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  225. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  226. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  227. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  228. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  229. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  230. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  231. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  232. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  233. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  234. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  235. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  236. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  237. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0,
  238. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  239. });
  240. correct_output_int = Mat1i(sizes, {
  241. 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8, 0,
  242. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  243. 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16, 0,
  244. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  245. 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24, 0,
  246. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  247. 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32, 0,
  248. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  249. 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40, 0,
  250. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  251. 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48, 0,
  252. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  253. 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56, 0,
  254. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  255. 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64, 0,
  256. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
  257. });
  258. }
  259. correct_output_int.convertTo(correct_output, CV_MAT_DEPTH(ltype));
  260. cv::Mat labels;
  261. cv::Mat diff;
  262. cv::cuda::GpuMat d_input;
  263. cv::cuda::GpuMat d_labels;
  264. d_input.upload(input);
  265. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_input, d_labels, connectivity, ltype, algo));
  266. d_labels.download(labels);
  267. normalize_labels(labels);
  268. diff = labels != correct_output;
  269. EXPECT_EQ(cv::countNonZero(diff), 0);
  270. }
  271. CUDA_TEST_P(ConnectedComponents, Maxlabels_8conn_Odd)
  272. {
  273. std::initializer_list<int> sizes{ 15, 15 };
  274. cv::Mat1b input;
  275. cv::Mat1i correct_output_int;
  276. cv::Mat correct_output;
  277. // Chessboard image with even number of rows and cols
  278. // Note that this is the maximum number of labels for 4-way connectivity
  279. {
  280. input = Mat1b(sizes, {
  281. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  282. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  283. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  284. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  285. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  286. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  287. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  288. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  289. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  290. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  291. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  292. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  293. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1,
  294. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  295. 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1
  296. });
  297. correct_output_int = Mat1i(sizes, {
  298. 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8,
  299. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  300. 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 15, 0, 16,
  301. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  302. 17, 0, 18, 0, 19, 0, 20, 0, 21, 0, 22, 0, 23, 0, 24,
  303. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  304. 25, 0, 26, 0, 27, 0, 28, 0, 29, 0, 30, 0, 31, 0, 32,
  305. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  306. 33, 0, 34, 0, 35, 0, 36, 0, 37, 0, 38, 0, 39, 0, 40,
  307. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  308. 41, 0, 42, 0, 43, 0, 44, 0, 45, 0, 46, 0, 47, 0, 48,
  309. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  310. 49, 0, 50, 0, 51, 0, 52, 0, 53, 0, 54, 0, 55, 0, 56,
  311. 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
  312. 57, 0, 58, 0, 59, 0, 60, 0, 61, 0, 62, 0, 63, 0, 64
  313. });
  314. }
  315. correct_output_int.convertTo(correct_output, CV_MAT_DEPTH(ltype));
  316. cv::Mat labels;
  317. cv::Mat diff;
  318. cv::cuda::GpuMat d_input;
  319. cv::cuda::GpuMat d_labels;
  320. d_input.upload(input);
  321. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_input, d_labels, connectivity, ltype, algo));
  322. d_labels.download(labels);
  323. normalize_labels(labels);
  324. diff = labels != correct_output;
  325. EXPECT_EQ(cv::countNonZero(diff), 0);
  326. }
  327. CUDA_TEST_P(ConnectedComponents, Single_Row)
  328. {
  329. std::initializer_list<int> sizes{ 1, 15 };
  330. cv::Mat1b input;
  331. cv::Mat1i correct_output_int;
  332. cv::Mat correct_output;
  333. // Chessboard image with even number of rows and cols
  334. // Note that this is the maximum number of labels for 4-way connectivity
  335. {
  336. input = Mat1b(sizes, { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
  337. correct_output_int = Mat1i(sizes, { 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 });
  338. }
  339. correct_output_int.convertTo(correct_output, CV_MAT_DEPTH(ltype));
  340. cv::Mat labels;
  341. cv::Mat diff;
  342. cv::cuda::GpuMat d_input;
  343. cv::cuda::GpuMat d_labels;
  344. d_input.upload(input);
  345. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_input, d_labels, connectivity, ltype, algo));
  346. d_labels.download(labels);
  347. normalize_labels(labels);
  348. diff = labels != correct_output;
  349. EXPECT_EQ(cv::countNonZero(diff), 0);
  350. }
  351. CUDA_TEST_P(ConnectedComponents, Single_Column)
  352. {
  353. std::initializer_list<int> sizes{ 15, 1 };
  354. cv::Mat1b input;
  355. cv::Mat1i correct_output_int;
  356. cv::Mat correct_output;
  357. // Chessboard image with even number of rows and cols
  358. // Note that this is the maximum number of labels for 4-way connectivity
  359. {
  360. input = Mat1b(sizes, { 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1 });
  361. correct_output_int = Mat1i(sizes, { 1, 0, 2, 0, 3, 0, 4, 0, 5, 0, 6, 0, 7, 0, 8 });
  362. }
  363. correct_output_int.convertTo(correct_output, CV_MAT_DEPTH(ltype));
  364. cv::Mat labels;
  365. cv::Mat diff;
  366. cv::cuda::GpuMat d_input;
  367. cv::cuda::GpuMat d_labels;
  368. d_input.upload(input);
  369. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_input, d_labels, connectivity, ltype, algo));
  370. d_labels.download(labels);
  371. normalize_labels(labels);
  372. diff = labels != correct_output;
  373. EXPECT_EQ(cv::countNonZero(diff), 0);
  374. }
  375. CUDA_TEST_P(ConnectedComponents, Concentric_Circles)
  376. {
  377. string img_path = cvtest::TS::ptr()->get_data_path() + "connectedcomponents/concentric_circles.png";
  378. string exp_path = cvtest::TS::ptr()->get_data_path() + "connectedcomponents/ccomp_exp.png";
  379. Mat img = imread(img_path, 0);
  380. EXPECT_FALSE(img.empty());
  381. Mat exp = imread(exp_path, 0);
  382. EXPECT_FALSE(exp.empty());
  383. Mat labels;
  384. exp.convertTo(exp, ltype);
  385. GpuMat d_img;
  386. GpuMat d_labels;
  387. d_img.upload(img);
  388. EXPECT_NO_THROW(cv::cuda::connectedComponents(d_img, d_labels, connectivity, ltype, algo));
  389. d_labels.download(labels);
  390. normalize_labels(labels);
  391. Mat diff = labels != exp;
  392. EXPECT_EQ(cv::countNonZero(diff), 0);
  393. }
  394. INSTANTIATE_TEST_CASE_P(CUDA_ImgProc, ConnectedComponents, testing::Combine(
  395. ALL_DEVICES,
  396. testing::Values(8),
  397. testing::Values(CV_32S),
  398. testing::Values(cv::cuda::CCL_DEFAULT, cv::cuda::CCL_BKE)
  399. ));
  400. }
  401. } // namespace
  402. #endif // HAVE_CUDA