test_intelligent_scissors.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496
  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. //#include "opencv2/imgproc/segmentation.hpp"
  6. namespace opencv_test { namespace {
  7. Mat getTestImageGray()
  8. {
  9. static Mat m;
  10. if (m.empty())
  11. {
  12. m = imread(findDataFile("shared/lena.png"), IMREAD_GRAYSCALE);
  13. }
  14. return m.clone();
  15. }
  16. Mat getTestImageColor()
  17. {
  18. static Mat m;
  19. if (m.empty())
  20. {
  21. m = imread(findDataFile("shared/lena.png"), IMREAD_COLOR);
  22. }
  23. return m.clone();
  24. }
  25. Mat getTestImage1()
  26. {
  27. static Mat m;
  28. if (m.empty())
  29. {
  30. m.create(Size(200, 100), CV_8UC1);
  31. m.setTo(Scalar::all(128));
  32. Rect roi(50, 30, 100, 40);
  33. m(roi).setTo(Scalar::all(0));
  34. #if 0
  35. imshow("image", m);
  36. waitKey();
  37. #endif
  38. }
  39. return m.clone();
  40. }
  41. Mat getTestImage2()
  42. {
  43. static Mat m;
  44. if (m.empty())
  45. {
  46. m.create(Size(200, 100), CV_8UC1);
  47. m.setTo(Scalar::all(128));
  48. Rect roi(40, 30, 100, 40);
  49. m(roi).setTo(Scalar::all(255));
  50. #if 0
  51. imshow("image", m);
  52. waitKey();
  53. #endif
  54. }
  55. return m.clone();
  56. }
  57. Mat getTestImage3()
  58. {
  59. static Mat m;
  60. if (m.empty())
  61. {
  62. m.create(Size(200, 100), CV_8UC1);
  63. m.setTo(Scalar::all(128));
  64. Scalar color(0,0,0,0);
  65. line(m, Point(30, 50), Point(50, 50), color, 1);
  66. line(m, Point(50, 50), Point(80, 30), color, 1);
  67. line(m, Point(150, 50), Point(80, 30), color, 1);
  68. line(m, Point(150, 50), Point(180, 50), color, 1);
  69. line(m, Point(80, 10), Point(80, 90), Scalar::all(200), 1);
  70. line(m, Point(100, 10), Point(100, 90), Scalar::all(200), 1);
  71. line(m, Point(120, 10), Point(120, 90), Scalar::all(200), 1);
  72. #if 0
  73. imshow("image", m);
  74. waitKey();
  75. #endif
  76. }
  77. return m.clone();
  78. }
  79. Mat getTestImage4()
  80. {
  81. static Mat m;
  82. if (m.empty())
  83. {
  84. m.create(Size(200, 100), CV_8UC1);
  85. for (int y = 0; y < m.rows; y++)
  86. {
  87. for (int x = 0; x < m.cols; x++)
  88. {
  89. float dx = (float)(x - 100);
  90. float dy = (float)(y - 100);
  91. float d = sqrtf(dx * dx + dy * dy);
  92. m.at<uchar>(y, x) = saturate_cast<uchar>(100 + 100 * sin(d / 10 * CV_PI));
  93. }
  94. }
  95. #if 0
  96. imshow("image", m);
  97. waitKey();
  98. #endif
  99. }
  100. return m.clone();
  101. }
  102. Mat getTestImage5()
  103. {
  104. static Mat m;
  105. if (m.empty())
  106. {
  107. m.create(Size(200, 100), CV_8UC1);
  108. for (int y = 0; y < m.rows; y++)
  109. {
  110. for (int x = 0; x < m.cols; x++)
  111. {
  112. float dx = (float)(x - 100);
  113. float dy = (float)(y - 100);
  114. float d = sqrtf(dx * dx + dy * dy);
  115. m.at<uchar>(y, x) = saturate_cast<uchar>(x / 2 + 100 * sin(d / 10 * CV_PI));
  116. }
  117. }
  118. #if 0
  119. imshow("image", m);
  120. waitKey();
  121. #endif
  122. }
  123. return m.clone();
  124. }
  125. void show(const Mat& img, const std::vector<Point> pts)
  126. {
  127. if (cvtest::debugLevel >= 10)
  128. {
  129. Mat dst = img.clone();
  130. std::vector< std::vector<Point> > contours;
  131. contours.push_back(pts);
  132. polylines(dst, contours, false, Scalar::all(255));
  133. imshow("dst", dst);
  134. waitKey();
  135. }
  136. }
  137. Size estimateContourSize(const std::vector<Point>& pts)
  138. {
  139. Size s(0,0);
  140. for (size_t i = 0; i < pts.size(); i++)
  141. {
  142. if (s.width < pts[i].x)
  143. s.width = pts[i].x;
  144. if (s.height < pts[i].y)
  145. s.height = pts[i].y;
  146. }
  147. return s;
  148. }
  149. int contoursAreaPixelsMismatch(const std::vector<Point>& pts, const std::vector<Point>& gt)
  150. {
  151. Size ptsSize = estimateContourSize(pts);
  152. Size gtSize = estimateContourSize(gt);
  153. Size imgSize(std::max(ptsSize.width, gtSize.width)+1, std::max(ptsSize.height, gtSize.height)+1);
  154. Mat ptsArea = Mat::zeros(imgSize, CV_8UC1);
  155. Mat gtArea = Mat::zeros(imgSize, CV_8UC1);
  156. std::vector<std::vector<Point>> pts_wrapped = {pts};
  157. std::vector<std::vector<Point>> gt_wrapped = {gt};
  158. drawContours(ptsArea, pts_wrapped, -1, Scalar(255), FILLED);
  159. drawContours(gtArea, gt_wrapped, -1, Scalar(255), FILLED);
  160. Mat uni = ptsArea | gtArea;
  161. Mat intersection = ptsArea & gtArea;
  162. bitwise_not(intersection, intersection);
  163. Mat delta = uni & intersection;
  164. return countNonZero(delta);
  165. }
  166. void checkContour(std::vector<Point>& pts,
  167. const bool backward = false,
  168. int allowed_mismatch = 0)
  169. {
  170. const ::testing::TestInfo* const test_info = ::testing::UnitTest::GetInstance()->current_test_info();
  171. CV_Assert(test_info);
  172. const std::string name = std::string(cvtest::TS::ptr()->get_data_path() + "imgproc/" + test_info->test_case_name() + "-" + test_info->name() + (backward ? "-backward" : "") + ".xml");
  173. std::vector<Point> reference_pts;
  174. #ifdef GENERATE_TEST_DATA
  175. {
  176. cv::FileStorage fs(name, cv::FileStorage::WRITE);
  177. fs << "pts" << pts;
  178. }
  179. reference_pts = pts;
  180. #else
  181. FileStorage fs(name, FileStorage::READ);
  182. read(fs["pts"], reference_pts, std::vector<Point>());
  183. #endif
  184. if (!allowed_mismatch)
  185. EXPECT_EQ(pts, reference_pts);
  186. else
  187. EXPECT_LE(contoursAreaPixelsMismatch(pts, reference_pts), allowed_mismatch);
  188. }
  189. TEST(Imgproc_IntelligentScissorsMB, rect)
  190. {
  191. segmentation::IntelligentScissorsMB tool;
  192. Mat image = getTestImage1();
  193. tool.applyImage(image);
  194. Point source_point(50, 30);
  195. tool.buildMap(source_point);
  196. Point target_point(100, 30);
  197. std::vector<Point> pts;
  198. tool.getContour(target_point, pts);
  199. checkContour(pts);
  200. show(image, pts);
  201. Mat image2 = getTestImage2();
  202. tool.applyImage(image2);
  203. tool.buildMap(source_point);
  204. std::vector<Point> pts2;
  205. tool.getContour(target_point, pts2, true/*backward*/);
  206. checkContour(pts2, true/*backward*/);
  207. show(image2, pts2);
  208. }
  209. TEST(Imgproc_IntelligentScissorsMB, lines)
  210. {
  211. segmentation::IntelligentScissorsMB tool;
  212. Mat image = getTestImage3();
  213. tool.applyImage(image);
  214. Point source_point(30, 50);
  215. tool.buildMap(source_point);
  216. Point target_point(150, 50);
  217. std::vector<Point> pts;
  218. tool.getContour(target_point, pts);
  219. checkContour(pts);
  220. show(image, pts);
  221. }
  222. TEST(Imgproc_IntelligentScissorsMB, circles)
  223. {
  224. segmentation::IntelligentScissorsMB tool;
  225. tool.setGradientMagnitudeMaxLimit(10);
  226. Mat image = getTestImage4();
  227. tool.applyImage(image);
  228. Point source_point(50, 50);
  229. tool.buildMap(source_point);
  230. Point target_point(150, 50);
  231. std::vector<Point> pts;
  232. tool.getContour(target_point, pts);
  233. checkContour(pts);
  234. show(image, pts);
  235. }
  236. TEST(Imgproc_IntelligentScissorsMB, circles_gradient)
  237. {
  238. segmentation::IntelligentScissorsMB tool;
  239. Mat image = getTestImage5();
  240. tool.applyImage(image);
  241. Point source_point(50, 50);
  242. tool.buildMap(source_point);
  243. Point target_point(150, 50);
  244. std::vector<Point> pts;
  245. tool.getContour(target_point, pts);
  246. checkContour(pts);
  247. show(image, pts);
  248. }
  249. TEST(Imgproc_IntelligentScissorsMB, grayscale)
  250. {
  251. segmentation::IntelligentScissorsMB tool;
  252. Mat image = getTestImageGray();
  253. tool.applyImage(image);
  254. Point source_point(275, 63);
  255. tool.buildMap(source_point);
  256. Point target_point(413, 155);
  257. std::vector<Point> pts;
  258. tool.getContour(target_point, pts);
  259. checkContour(pts, false, 2);
  260. show(image, pts);
  261. }
  262. TEST(Imgproc_IntelligentScissorsMB, check_features_grayscale_1_0_0_zerro_crossing_with_limit)
  263. {
  264. segmentation::IntelligentScissorsMB tool;
  265. tool.setEdgeFeatureZeroCrossingParameters(64);
  266. tool.setWeights(1.0f, 0.0f, 0.0f);
  267. Mat image = getTestImageGray();
  268. tool.applyImage(image);
  269. Point source_point(275, 63);
  270. tool.buildMap(source_point);
  271. Point target_point(413, 155);
  272. std::vector<Point> pts;
  273. tool.getContour(target_point, pts);
  274. checkContour(pts, false, 11);
  275. show(image, pts);
  276. }
  277. TEST(Imgproc_IntelligentScissorsMB, check_features_grayscale_1_0_0_canny)
  278. {
  279. segmentation::IntelligentScissorsMB tool;
  280. tool.setEdgeFeatureCannyParameters(50, 100);
  281. tool.setWeights(1.0f, 0.0f, 0.0f);
  282. Mat image = getTestImageGray();
  283. tool.applyImage(image);
  284. Point source_point(275, 63);
  285. tool.buildMap(source_point);
  286. Point target_point(413, 155);
  287. std::vector<Point> pts;
  288. tool.getContour(target_point, pts);
  289. checkContour(pts, false, 6);
  290. show(image, pts);
  291. }
  292. TEST(Imgproc_IntelligentScissorsMB, check_features_grayscale_0_1_0)
  293. {
  294. segmentation::IntelligentScissorsMB tool;
  295. tool.setWeights(0.0f, 1.0f, 0.0f);
  296. Mat image = getTestImageGray();
  297. tool.applyImage(image);
  298. Point source_point(275, 63);
  299. tool.buildMap(source_point);
  300. Point target_point(413, 155);
  301. std::vector<Point> pts;
  302. tool.getContour(target_point, pts);
  303. checkContour(pts, false, 4);
  304. show(image, pts);
  305. }
  306. TEST(Imgproc_IntelligentScissorsMB, check_features_grayscale_0_0_1)
  307. {
  308. segmentation::IntelligentScissorsMB tool;
  309. tool.setWeights(0.0f, 0.0f, 1.0f);
  310. Mat image = getTestImageGray();
  311. tool.applyImage(image);
  312. Point source_point(275, 63);
  313. tool.buildMap(source_point);
  314. Point target_point(413, 155);
  315. std::vector<Point> pts;
  316. tool.getContour(target_point, pts);
  317. checkContour(pts, false, 2);
  318. show(image, pts);
  319. }
  320. TEST(Imgproc_IntelligentScissorsMB, color)
  321. {
  322. segmentation::IntelligentScissorsMB tool;
  323. Mat image = getTestImageColor();
  324. tool.applyImage(image);
  325. Point source_point(275, 63);
  326. tool.buildMap(source_point);
  327. Point target_point(413, 155);
  328. std::vector<Point> pts;
  329. tool.getContour(target_point, pts);
  330. checkContour(pts, false, 2);
  331. show(image, pts);
  332. }
  333. TEST(Imgproc_IntelligentScissorsMB, color_canny)
  334. {
  335. segmentation::IntelligentScissorsMB tool;
  336. tool.setEdgeFeatureCannyParameters(32, 100);
  337. Mat image = getTestImageColor();
  338. tool.applyImage(image);
  339. Point source_point(275, 63);
  340. tool.buildMap(source_point);
  341. Point target_point(413, 155);
  342. std::vector<Point> pts;
  343. tool.getContour(target_point, pts);
  344. checkContour(pts, false, 2);
  345. show(image, pts);
  346. }
  347. TEST(Imgproc_IntelligentScissorsMB, color_custom_features_invalid)
  348. {
  349. segmentation::IntelligentScissorsMB tool;
  350. ASSERT_ANY_THROW(tool.applyImageFeatures(noArray(), noArray(), noArray()));
  351. }
  352. TEST(Imgproc_IntelligentScissorsMB, color_custom_features_edge)
  353. {
  354. segmentation::IntelligentScissorsMB tool;
  355. Mat image = getTestImageColor();
  356. Mat canny_edges;
  357. Canny(image, canny_edges, 32, 100, 5);
  358. Mat binary_edge_feature;
  359. cv::threshold(canny_edges, binary_edge_feature, 254, 1, THRESH_BINARY_INV);
  360. tool.applyImageFeatures(binary_edge_feature, noArray(), noArray(), image);
  361. Point source_point(275, 63);
  362. tool.buildMap(source_point);
  363. Point target_point(413, 155);
  364. std::vector<Point> pts;
  365. tool.getContour(target_point, pts);
  366. checkContour(pts, false, 2);
  367. show(image, pts);
  368. }
  369. TEST(Imgproc_IntelligentScissorsMB, color_custom_features_all)
  370. {
  371. segmentation::IntelligentScissorsMB tool;
  372. tool.setWeights(0.9f, 0.0f, 0.1f);
  373. Mat image = getTestImageColor();
  374. Mat canny_edges;
  375. Canny(image, canny_edges, 50, 100, 5);
  376. Mat binary_edge_feature; // 0, 1 values
  377. cv::threshold(canny_edges, binary_edge_feature, 254, 1, THRESH_BINARY_INV);
  378. Mat_<Point2f> gradient_direction(image.size(), Point2f(0, 0)); // normalized
  379. Mat_<float> gradient_magnitude(image.size(), 0); // cost function
  380. tool.applyImageFeatures(binary_edge_feature, gradient_direction, gradient_magnitude);
  381. Point source_point(275, 63);
  382. tool.buildMap(source_point);
  383. Point target_point(413, 155);
  384. std::vector<Point> pts;
  385. tool.getContour(target_point, pts);
  386. checkContour(pts, false, 9);
  387. show(image, pts);
  388. }
  389. TEST(Imgproc_IntelligentScissorsMB, color_custom_features_edge_magnitude)
  390. {
  391. segmentation::IntelligentScissorsMB tool;
  392. tool.setWeights(0.9f, 0.0f, 0.1f);
  393. Mat image = getTestImageColor();
  394. Mat canny_edges;
  395. Canny(image, canny_edges, 50, 100, 5);
  396. Mat binary_edge_feature; // 0, 1 values
  397. cv::threshold(canny_edges, binary_edge_feature, 254, 1, THRESH_BINARY_INV);
  398. Mat_<float> gradient_magnitude(image.size(), 0); // cost function
  399. tool.applyImageFeatures(binary_edge_feature, noArray(), gradient_magnitude);
  400. Point source_point(275, 63);
  401. tool.buildMap(source_point);
  402. Point target_point(413, 155);
  403. std::vector<Point> pts;
  404. tool.getContour(target_point, pts);
  405. checkContour(pts, false, 9);
  406. show(image, pts);
  407. }
  408. }} // namespace