test_drawing.cpp 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  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. namespace opencv_test { namespace {
  44. //#define DRAW_TEST_IMAGE
  45. class CV_DrawingTest : public cvtest::BaseTest
  46. {
  47. public:
  48. CV_DrawingTest(){}
  49. protected:
  50. void run( int );
  51. virtual void draw( Mat& img ) = 0;
  52. virtual int checkLineIterator( Mat& img) = 0;
  53. virtual int checkLineVirtualIterator() = 0;
  54. };
  55. void CV_DrawingTest::run( int )
  56. {
  57. Mat testImg, valImg;
  58. const string fname = "../highgui/drawing/image.png";
  59. string path = ts->get_data_path(), filename;
  60. filename = path + fname;
  61. draw( testImg );
  62. valImg = imread( filename );
  63. if( valImg.empty() )
  64. {
  65. //imwrite( filename, testImg );
  66. ts->printf( ts->LOG, "test image can not be read");
  67. #ifdef HAVE_PNG
  68. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_TEST_DATA);
  69. #else
  70. ts->printf( ts->LOG, "PNG image support is not available");
  71. ts->set_failed_test_info(cvtest::TS::OK);
  72. #endif
  73. return;
  74. }
  75. else
  76. {
  77. // image should match exactly
  78. float err = (float)cvtest::norm( testImg, valImg, NORM_L1 );
  79. float Eps = 1;
  80. if( err > Eps)
  81. {
  82. ts->printf( ts->LOG, "NORM_L1 between testImg and valImg is equal %f (larger than %f)\n", err, Eps );
  83. ts->set_failed_test_info(cvtest::TS::FAIL_BAD_ACCURACY);
  84. }
  85. else
  86. {
  87. ts->set_failed_test_info(checkLineIterator( testImg ));
  88. }
  89. }
  90. ts->set_failed_test_info(checkLineVirtualIterator());
  91. ts->set_failed_test_info(cvtest::TS::OK);
  92. }
  93. class CV_DrawingTest_CPP : public CV_DrawingTest
  94. {
  95. public:
  96. CV_DrawingTest_CPP() {}
  97. protected:
  98. virtual void draw( Mat& img );
  99. virtual int checkLineIterator( Mat& img);
  100. virtual int checkLineVirtualIterator();
  101. };
  102. void CV_DrawingTest_CPP::draw( Mat& img )
  103. {
  104. Size imgSize( 600, 400 );
  105. img.create( imgSize, CV_8UC3 );
  106. vector<Point> polyline(4);
  107. polyline[0] = Point(0, 0);
  108. polyline[1] = Point(imgSize.width, 0);
  109. polyline[2] = Point(imgSize.width, imgSize.height);
  110. polyline[3] = Point(0, imgSize.height);
  111. const Point* pts = &polyline[0];
  112. int n = (int)polyline.size();
  113. fillPoly( img, &pts, &n, 1, Scalar::all(255) );
  114. Point p1(1,1), p2(3,3);
  115. if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
  116. circle( img, Point(300,100), 40, Scalar(0,0,255), 3 ); // draw
  117. p2 = Point(3,imgSize.height+1000);
  118. if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
  119. circle( img, Point(500,300), 50, cvColorToScalar(255,CV_8UC3), 5, 8, 1 ); // draw
  120. p1 = Point(imgSize.width,1), p2 = Point(imgSize.width,3);
  121. if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
  122. circle( img, Point(390,100), 10, Scalar(0,0,255), 3 ); // not draw
  123. p1 = Point(imgSize.width-1,1), p2 = Point(imgSize.width,3);
  124. if( clipLine(Rect(0,0,imgSize.width,imgSize.height), p1, p2) && clipLine(imgSize, p1, p2) )
  125. ellipse( img, Point(390,100), Size(20,30), 60, 0, 220.0, Scalar(0,200,0), 4 ); //draw
  126. ellipse( img, RotatedRect(Point(100,200),Size(200,100),160), Scalar(200,200,255), 5 );
  127. polyline.clear();
  128. ellipse2Poly( Point(430,180), Size(100,150), 30, 0, 150, 20, polyline );
  129. pts = &polyline[0];
  130. n = (int)polyline.size();
  131. polylines( img, &pts, &n, 1, false, Scalar(0,0,150), 4, CV_AA );
  132. n = 0;
  133. for( vector<Point>::const_iterator it = polyline.begin(); n < (int)polyline.size()-1; ++it, n++ )
  134. {
  135. line( img, *it, *(it+1), Scalar(50,250,100));
  136. }
  137. polyline.clear();
  138. ellipse2Poly( Point(500,300), Size(50,80), 0, 0, 180, 10, polyline );
  139. pts = &polyline[0];
  140. n = (int)polyline.size();
  141. polylines( img, &pts, &n, 1, true, Scalar(100,200,100), 20 );
  142. fillConvexPoly( img, pts, n, Scalar(0, 80, 0) );
  143. polyline.resize(8);
  144. // external rectengular
  145. polyline[0] = Point(0, 0);
  146. polyline[1] = Point(80, 0);
  147. polyline[2] = Point(80, 80);
  148. polyline[3] = Point(0, 80);
  149. // internal rectangular
  150. polyline[4] = Point(20, 20);
  151. polyline[5] = Point(60, 20);
  152. polyline[6] = Point(60, 60);
  153. polyline[7] = Point(20, 60);
  154. const Point* ppts[] = {&polyline[0], &polyline[0]+4};
  155. int pn[] = {4, 4};
  156. fillPoly( img, ppts, pn, 2, Scalar(100, 100, 0), 8, 0, Point(500, 20) );
  157. rectangle( img, Point(0, 300), Point(50, 398), Scalar(0,0,255) );
  158. string text1 = "OpenCV";
  159. int baseline = 0, thickness = 3, fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
  160. float fontScale = 2;
  161. Size textSize = getTextSize( text1, fontFace, fontScale, thickness, &baseline);
  162. baseline += thickness;
  163. Point textOrg((img.cols - textSize.width)/2, (img.rows + textSize.height)/2);
  164. rectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0,0,255));
  165. line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255));
  166. putText(img, text1, textOrg, fontFace, fontScale, Scalar(150,0,150), thickness, 8);
  167. string text2 = "abcdefghijklmnopqrstuvwxyz1234567890";
  168. Scalar color(200,0,0);
  169. fontScale = 0.5, thickness = 1;
  170. int dist = 5;
  171. textSize = getTextSize( text2, FONT_HERSHEY_SIMPLEX, fontScale, thickness, &baseline);
  172. textOrg = Point(5,5)+Point(0,textSize.height+dist);
  173. putText(img, text2, textOrg, FONT_HERSHEY_SIMPLEX, fontScale, color, thickness, CV_AA);
  174. fontScale = 1;
  175. textSize = getTextSize( text2, FONT_HERSHEY_PLAIN, fontScale, thickness, &baseline);
  176. textOrg += Point(0,textSize.height+dist);
  177. putText(img, text2, textOrg, FONT_HERSHEY_PLAIN, fontScale, color, thickness, CV_AA);
  178. fontScale = 0.5;
  179. textSize = getTextSize( text2, FONT_HERSHEY_DUPLEX, fontScale, thickness, &baseline);
  180. textOrg += Point(0,textSize.height+dist);
  181. putText(img, text2, textOrg, FONT_HERSHEY_DUPLEX, fontScale, color, thickness, CV_AA);
  182. textSize = getTextSize( text2, FONT_HERSHEY_COMPLEX, fontScale, thickness, &baseline);
  183. textOrg += Point(0,textSize.height+dist);
  184. putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX, fontScale, color, thickness, CV_AA);
  185. textSize = getTextSize( text2, FONT_HERSHEY_TRIPLEX, fontScale, thickness, &baseline);
  186. textOrg += Point(0,textSize.height+dist);
  187. putText(img, text2, textOrg, FONT_HERSHEY_TRIPLEX, fontScale, color, thickness, CV_AA);
  188. fontScale = 1;
  189. textSize = getTextSize( text2, FONT_HERSHEY_COMPLEX_SMALL, fontScale, thickness, &baseline);
  190. textOrg += Point(0,180) + Point(0,textSize.height+dist);
  191. putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX_SMALL, fontScale, color, thickness, CV_AA);
  192. textSize = getTextSize( text2, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, &baseline);
  193. textOrg += Point(0,textSize.height+dist);
  194. putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, color, thickness, CV_AA);
  195. textSize = getTextSize( text2, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, thickness, &baseline);
  196. textOrg += Point(0,textSize.height+dist);
  197. putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, color, thickness, CV_AA);
  198. dist = 15, fontScale = 0.5;
  199. textSize = getTextSize( text2, FONT_ITALIC, fontScale, thickness, &baseline);
  200. textOrg += Point(0,textSize.height+dist);
  201. putText(img, text2, textOrg, FONT_ITALIC, fontScale, color, thickness, CV_AA);
  202. }
  203. int CV_DrawingTest_CPP::checkLineIterator( Mat& img )
  204. {
  205. LineIterator it( img, Point(0,300), Point(1000, 300) );
  206. for(int i = 0; i < it.count; ++it, i++ )
  207. {
  208. Vec3b v = (Vec3b)(*(*it)) - img.at<Vec3b>(300,i);
  209. float err = (float)cvtest::norm( v, NORM_L2 );
  210. if( err != 0 )
  211. {
  212. ts->printf( ts->LOG, "LineIterator works incorrect" );
  213. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  214. }
  215. }
  216. ts->set_failed_test_info(cvtest::TS::OK);
  217. return 0;
  218. }
  219. int CV_DrawingTest_CPP::checkLineVirtualIterator( )
  220. {
  221. RNG randomGenerator(1);
  222. for (size_t test = 0; test < 10000; ++test)
  223. {
  224. int width = randomGenerator.uniform(0, 512+1);
  225. int height = randomGenerator.uniform(0, 512+1);
  226. int x1 = randomGenerator.uniform(-512, 1024+1);
  227. int y1 = randomGenerator.uniform(-512, 1024+1);
  228. int x2 = randomGenerator.uniform(-512, 1024+1);
  229. int y2 = randomGenerator.uniform(-512, 1024+1);
  230. int x3 = randomGenerator.uniform(-512, 1024+1);
  231. int y3 = randomGenerator.uniform(-512, 1024+1);
  232. int channels = randomGenerator.uniform(1, 3+1);
  233. Mat m(cv::Size(width, height), CV_MAKETYPE(8U, channels));
  234. Point p1(x1, y1);
  235. Point p2(x2, y2);
  236. Point offset(x3, y3);
  237. LineIterator it( m, p1, p2 );
  238. LineIterator vit(Rect(offset.x, offset.y, width, height), p1 + offset, p2 + offset);
  239. if (it.count != vit.count)
  240. {
  241. ts->printf( ts->LOG, "virtual LineIterator works incorrectly" );
  242. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  243. break;
  244. }
  245. else
  246. {
  247. for(int i = 0; i < it.count; ++it, ++vit, i++ )
  248. {
  249. Point pIt = it.pos();
  250. Point pVit = vit.pos() - offset;
  251. if (pIt != pVit)
  252. {
  253. ts->printf( ts->LOG, "virtual LineIterator works incorrectly" );
  254. ts->set_failed_test_info(cvtest::TS::FAIL_INVALID_OUTPUT);
  255. break;
  256. }
  257. }
  258. }
  259. }
  260. ts->set_failed_test_info(cvtest::TS::OK);
  261. return 0;
  262. }
  263. class CV_DrawingTest_Far : public CV_DrawingTest_CPP
  264. {
  265. public:
  266. CV_DrawingTest_Far() {}
  267. protected:
  268. virtual void draw(Mat& img);
  269. };
  270. void CV_DrawingTest_Far::draw(Mat& img)
  271. {
  272. Size imgSize(32768 + 600, 400);
  273. img.create(imgSize, CV_8UC3);
  274. vector<Point> polyline(4);
  275. polyline[0] = Point(32768 + 0, 0);
  276. polyline[1] = Point(imgSize.width, 0);
  277. polyline[2] = Point(imgSize.width, imgSize.height);
  278. polyline[3] = Point(32768 + 0, imgSize.height);
  279. const Point* pts = &polyline[0];
  280. int n = (int)polyline.size();
  281. fillPoly(img, &pts, &n, 1, Scalar::all(255));
  282. Point p1(32768 + 1, 1), p2(32768 + 3, 3);
  283. if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2))
  284. circle(img, Point(32768 + 300, 100), 40, Scalar(0, 0, 255), 3); // draw
  285. p2 = Point(32768 + 3, imgSize.height + 1000);
  286. if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2))
  287. circle(img, Point(65536 + 500, 300), 50, cvColorToScalar(255, CV_8UC3), 5, 8, 1); // draw
  288. p1 = Point(imgSize.width, 1), p2 = Point(imgSize.width, 3);
  289. if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2))
  290. circle(img, Point(32768 + 390, 100), 10, Scalar(0, 0, 255), 3); // not draw
  291. p1 = Point(imgSize.width - 1, 1), p2 = Point(imgSize.width, 3);
  292. if (clipLine(Rect(32768 + 0, 0, imgSize.width, imgSize.height), p1, p2) && clipLine(imgSize, p1, p2))
  293. ellipse(img, Point(32768 + 390, 100), Size(20, 30), 60, 0, 220.0, Scalar(0, 200, 0), 4); //draw
  294. ellipse(img, RotatedRect(Point(32768 + 100, 200), Size(200, 100), 160), Scalar(200, 200, 255), 5);
  295. polyline.clear();
  296. ellipse2Poly(Point(32768 + 430, 180), Size(100, 150), 30, 0, 150, 20, polyline);
  297. pts = &polyline[0];
  298. n = (int)polyline.size();
  299. polylines(img, &pts, &n, 1, false, Scalar(0, 0, 150), 4, CV_AA);
  300. n = 0;
  301. for (vector<Point>::const_iterator it = polyline.begin(); n < (int)polyline.size() - 1; ++it, n++)
  302. {
  303. line(img, *it, *(it + 1), Scalar(50, 250, 100));
  304. }
  305. polyline.clear();
  306. ellipse2Poly(Point(32768 + 500, 300), Size(50, 80), 0, 0, 180, 10, polyline);
  307. pts = &polyline[0];
  308. n = (int)polyline.size();
  309. polylines(img, &pts, &n, 1, true, Scalar(100, 200, 100), 20);
  310. fillConvexPoly(img, pts, n, Scalar(0, 80, 0));
  311. polyline.resize(8);
  312. // external rectengular
  313. polyline[0] = Point(32768 + 0, 0);
  314. polyline[1] = Point(32768 + 80, 0);
  315. polyline[2] = Point(32768 + 80, 80);
  316. polyline[3] = Point(32768 + 0, 80);
  317. // internal rectangular
  318. polyline[4] = Point(32768 + 20, 20);
  319. polyline[5] = Point(32768 + 60, 20);
  320. polyline[6] = Point(32768 + 60, 60);
  321. polyline[7] = Point(32768 + 20, 60);
  322. const Point* ppts[] = { &polyline[0], &polyline[0] + 4 };
  323. int pn[] = { 4, 4 };
  324. fillPoly(img, ppts, pn, 2, Scalar(100, 100, 0), 8, 0, Point(500, 20));
  325. rectangle(img, Point(32768 + 0, 300), Point(32768 + 50, 398), Scalar(0, 0, 255));
  326. string text1 = "OpenCV";
  327. int baseline = 0, thickness = 3, fontFace = FONT_HERSHEY_SCRIPT_SIMPLEX;
  328. float fontScale = 2;
  329. Size textSize = getTextSize(text1, fontFace, fontScale, thickness, &baseline);
  330. baseline += thickness;
  331. Point textOrg((32768 + img.cols - textSize.width) / 2, (img.rows + textSize.height) / 2);
  332. rectangle(img, textOrg + Point(0, baseline), textOrg + Point(textSize.width, -textSize.height), Scalar(0, 0, 255));
  333. line(img, textOrg + Point(0, thickness), textOrg + Point(textSize.width, thickness), Scalar(0, 0, 255));
  334. putText(img, text1, textOrg, fontFace, fontScale, Scalar(150, 0, 150), thickness, 8);
  335. string text2 = "abcdefghijklmnopqrstuvwxyz1234567890";
  336. Scalar color(200, 0, 0);
  337. fontScale = 0.5, thickness = 1;
  338. int dist = 5;
  339. textSize = getTextSize(text2, FONT_HERSHEY_SIMPLEX, fontScale, thickness, &baseline);
  340. textOrg = Point(32768 + 5, 5) + Point(0, textSize.height + dist);
  341. putText(img, text2, textOrg, FONT_HERSHEY_SIMPLEX, fontScale, color, thickness, CV_AA);
  342. fontScale = 1;
  343. textSize = getTextSize(text2, FONT_HERSHEY_PLAIN, fontScale, thickness, &baseline);
  344. textOrg += Point(0, textSize.height + dist);
  345. putText(img, text2, textOrg, FONT_HERSHEY_PLAIN, fontScale, color, thickness, CV_AA);
  346. fontScale = 0.5;
  347. textSize = getTextSize(text2, FONT_HERSHEY_DUPLEX, fontScale, thickness, &baseline);
  348. textOrg += Point(0, textSize.height + dist);
  349. putText(img, text2, textOrg, FONT_HERSHEY_DUPLEX, fontScale, color, thickness, CV_AA);
  350. textSize = getTextSize(text2, FONT_HERSHEY_COMPLEX, fontScale, thickness, &baseline);
  351. textOrg += Point(0, textSize.height + dist);
  352. putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX, fontScale, color, thickness, CV_AA);
  353. textSize = getTextSize(text2, FONT_HERSHEY_TRIPLEX, fontScale, thickness, &baseline);
  354. textOrg += Point(0, textSize.height + dist);
  355. putText(img, text2, textOrg, FONT_HERSHEY_TRIPLEX, fontScale, color, thickness, CV_AA);
  356. fontScale = 1;
  357. textSize = getTextSize(text2, FONT_HERSHEY_COMPLEX_SMALL, fontScale, thickness, &baseline);
  358. textOrg += Point(0, 180) + Point(0, textSize.height + dist);
  359. putText(img, text2, textOrg, FONT_HERSHEY_COMPLEX_SMALL, fontScale, color, thickness, CV_AA);
  360. textSize = getTextSize(text2, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, thickness, &baseline);
  361. textOrg += Point(0, textSize.height + dist);
  362. putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_SIMPLEX, fontScale, color, thickness, CV_AA);
  363. textSize = getTextSize(text2, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, thickness, &baseline);
  364. textOrg += Point(0, textSize.height + dist);
  365. putText(img, text2, textOrg, FONT_HERSHEY_SCRIPT_COMPLEX, fontScale, color, thickness, CV_AA);
  366. dist = 15, fontScale = 0.5;
  367. textSize = getTextSize(text2, FONT_ITALIC, fontScale, thickness, &baseline);
  368. textOrg += Point(0, textSize.height + dist);
  369. putText(img, text2, textOrg, FONT_ITALIC, fontScale, color, thickness, CV_AA);
  370. img = img(Rect(32768, 0, 600, 400)).clone();
  371. }
  372. TEST(Drawing, cpp_regression) { CV_DrawingTest_CPP test; test.safe_run(); }
  373. TEST(Drawing, far_regression) { CV_DrawingTest_Far test; test.safe_run(); }
  374. class CV_FillConvexPolyTest : public cvtest::BaseTest
  375. {
  376. public:
  377. CV_FillConvexPolyTest() {}
  378. ~CV_FillConvexPolyTest() {}
  379. protected:
  380. void run(int)
  381. {
  382. vector<Point> line1;
  383. vector<Point> line2;
  384. line1.push_back(Point(1, 1));
  385. line1.push_back(Point(5, 1));
  386. line1.push_back(Point(5, 8));
  387. line1.push_back(Point(1, 8));
  388. line2.push_back(Point(2, 2));
  389. line2.push_back(Point(10, 2));
  390. line2.push_back(Point(10, 16));
  391. line2.push_back(Point(2, 16));
  392. Mat gray0(10,10,CV_8U, Scalar(0));
  393. fillConvexPoly(gray0, line1, Scalar(255), 8, 0);
  394. int nz1 = countNonZero(gray0);
  395. fillConvexPoly(gray0, line2, Scalar(0), 8, 1);
  396. int nz2 = countNonZero(gray0)/255;
  397. CV_Assert( nz1 == 40 && nz2 == 0 );
  398. }
  399. };
  400. TEST(Drawing, fillconvexpoly_clipping) { CV_FillConvexPolyTest test; test.safe_run(); }
  401. class CV_DrawingTest_UTF8 : public cvtest::BaseTest
  402. {
  403. public:
  404. CV_DrawingTest_UTF8() {}
  405. ~CV_DrawingTest_UTF8() {}
  406. protected:
  407. void run(int)
  408. {
  409. vector<string> lines;
  410. lines.push_back("abcdefghijklmnopqrstuvwxyz1234567890");
  411. // cyrillic letters small
  412. lines.push_back("\xD0\xB0\xD0\xB1\xD0\xB2\xD0\xB3\xD0\xB4\xD0\xB5\xD1\x91\xD0\xB6\xD0\xB7"
  413. "\xD0\xB8\xD0\xB9\xD0\xBA\xD0\xBB\xD0\xBC\xD0\xBD\xD0\xBE\xD0\xBF\xD1\x80"
  414. "\xD1\x81\xD1\x82\xD1\x83\xD1\x84\xD1\x85\xD1\x86\xD1\x87\xD1\x88\xD1\x89"
  415. "\xD1\x8A\xD1\x8B\xD1\x8C\xD1\x8D\xD1\x8E\xD1\x8F");
  416. // cyrillic letters capital
  417. lines.push_back("\xD0\x90\xD0\x91\xD0\x92\xD0\x93\xD0\x94\xD0\x95\xD0\x81\xD0\x96\xD0\x97"
  418. "\xD0\x98\xD0\x99\xD0\x9A\xD0\x9B\xD0\x9C\xD0\x9D\xD0\x9E\xD0\x9F\xD0\xA0"
  419. "\xD0\xA1\xD0\xA2\xD0\xA3\xD0\xA4\xD0\xA5\xD0\xA6\xD0\xA7\xD0\xA8\xD0\xA9"
  420. "\xD0\xAA\xD0\xAB\xD0\xAC\xD0\xAD\xD0\xAE\xD0\xAF");
  421. // bounds
  422. lines.push_back("-\xD0\x80-\xD0\x8E-\xD0\x8F-");
  423. lines.push_back("-\xD1\x90-\xD1\x91-\xD1\xBF-");
  424. // bad utf8
  425. lines.push_back("-\x81-\x82-\x83-");
  426. lines.push_back("--\xF0--");
  427. lines.push_back("-\xF0");
  428. vector<int> fonts;
  429. fonts.push_back(FONT_HERSHEY_SIMPLEX);
  430. fonts.push_back(FONT_HERSHEY_PLAIN);
  431. fonts.push_back(FONT_HERSHEY_DUPLEX);
  432. fonts.push_back(FONT_HERSHEY_COMPLEX);
  433. fonts.push_back(FONT_HERSHEY_TRIPLEX);
  434. fonts.push_back(FONT_HERSHEY_COMPLEX_SMALL);
  435. fonts.push_back(FONT_HERSHEY_SCRIPT_SIMPLEX);
  436. fonts.push_back(FONT_HERSHEY_SCRIPT_COMPLEX);
  437. vector<Mat> results;
  438. Size bigSize(0, 0);
  439. for (vector<int>::const_iterator font = fonts.begin(); font != fonts.end(); ++font)
  440. {
  441. for (int italic = 0; italic <= FONT_ITALIC; italic += FONT_ITALIC)
  442. {
  443. for (vector<string>::const_iterator line = lines.begin(); line != lines.end(); ++line)
  444. {
  445. const float fontScale = 1;
  446. const int thickness = 1;
  447. const Scalar color(20,20,20);
  448. int baseline = 0;
  449. Size textSize = getTextSize(*line, *font | italic, fontScale, thickness, &baseline);
  450. Point textOrg(0, textSize.height + 2);
  451. Mat img(textSize + Size(0, baseline), CV_8UC3, Scalar(255, 255, 255));
  452. putText(img, *line, textOrg, *font | italic, fontScale, color, thickness, CV_AA);
  453. results.push_back(img);
  454. bigSize.width = max(bigSize.width, img.size().width);
  455. bigSize.height += img.size().height + 1;
  456. }
  457. }
  458. }
  459. int shift = 0;
  460. Mat result(bigSize, CV_8UC3, Scalar(100, 100, 100));
  461. for (vector<Mat>::const_iterator img = results.begin(); img != results.end(); ++img)
  462. {
  463. Rect roi(Point(0, shift), img->size());
  464. Mat sub(result, roi);
  465. img->copyTo(sub);
  466. shift += img->size().height + 1;
  467. }
  468. if (cvtest::debugLevel > 0)
  469. imwrite("all_fonts.png", result);
  470. }
  471. };
  472. TEST(Drawing, utf8_support) { CV_DrawingTest_UTF8 test; test.safe_run(); }
  473. TEST(Drawing, _914)
  474. {
  475. const int rows = 256;
  476. const int cols = 256;
  477. Mat img(rows, cols, CV_8UC1, Scalar(255));
  478. line(img, Point(0, 10), Point(255, 10), Scalar(0), 2, 4);
  479. line(img, Point(-5, 20), Point(260, 20), Scalar(0), 2, 4);
  480. line(img, Point(10, 0), Point(10, 255), Scalar(0), 2, 4);
  481. double x0 = 0.0/pow(2.0, -2.0);
  482. double x1 = 255.0/pow(2.0, -2.0);
  483. double y = 30.5/pow(2.0, -2.0);
  484. line(img, Point(int(x0), int(y)), Point(int(x1), int(y)), Scalar(0), 2, 4, 2);
  485. int pixelsDrawn = rows*cols - countNonZero(img);
  486. ASSERT_EQ( (3*rows + cols)*3 - 3*9, pixelsDrawn);
  487. }
  488. TEST(Drawing, polylines_empty)
  489. {
  490. Mat img(100, 100, CV_8UC1, Scalar(0));
  491. vector<Point> pts; // empty
  492. polylines(img, pts, false, Scalar(255));
  493. int cnt = countNonZero(img);
  494. ASSERT_EQ(cnt, 0);
  495. }
  496. TEST(Drawing, polylines)
  497. {
  498. Mat img(100, 100, CV_8UC1, Scalar(0));
  499. vector<Point> pts;
  500. pts.push_back(Point(0, 0));
  501. pts.push_back(Point(20, 0));
  502. polylines(img, pts, false, Scalar(255));
  503. int cnt = countNonZero(img);
  504. ASSERT_EQ(cnt, 21);
  505. }
  506. TEST(Drawing, longline)
  507. {
  508. Mat mat = Mat::zeros(256, 256, CV_8UC1);
  509. line(mat, cv::Point(34, 204), cv::Point(46400, 47400), cv::Scalar(255), 3);
  510. EXPECT_EQ(310, cv::countNonZero(mat));
  511. Point pt[6];
  512. pt[0].x = 32;
  513. pt[0].y = 204;
  514. pt[1].x = 34;
  515. pt[1].y = 202;
  516. pt[2].x = 87;
  517. pt[2].y = 255;
  518. pt[3].x = 82;
  519. pt[3].y = 255;
  520. pt[4].x = 37;
  521. pt[4].y = 210;
  522. pt[5].x = 37;
  523. pt[5].y = 209;
  524. fillConvexPoly(mat, pt, 6, cv::Scalar(0));
  525. EXPECT_EQ(0, cv::countNonZero(mat));
  526. }
  527. TEST(Drawing, putText_no_garbage)
  528. {
  529. Size sz(640, 480);
  530. Mat mat = Mat::zeros(sz, CV_8UC1);
  531. mat = Scalar::all(0);
  532. putText(mat, "029", Point(10, 350), 0, 10, Scalar(128), 15);
  533. EXPECT_EQ(0, cv::countNonZero(mat(Rect(0, 0, 10, sz.height))));
  534. EXPECT_EQ(0, cv::countNonZero(mat(Rect(sz.width-10, 0, 10, sz.height))));
  535. EXPECT_EQ(0, cv::countNonZero(mat(Rect(205, 0, 10, sz.height))));
  536. EXPECT_EQ(0, cv::countNonZero(mat(Rect(405, 0, 10, sz.height))));
  537. }
  538. TEST(Drawing, line)
  539. {
  540. Mat mat = Mat::zeros(Size(100,100), CV_8UC1);
  541. ASSERT_THROW(line(mat, Point(1,1),Point(99,99),Scalar(255),0), cv::Exception);
  542. }
  543. TEST(Drawing, regression_16308)
  544. {
  545. Mat_<uchar> img(Size(100, 100), (uchar)0);
  546. circle(img, Point(50, 50), 50, 255, 1, LINE_AA);
  547. EXPECT_NE(0, (int)img.at<uchar>(0, 50));
  548. EXPECT_NE(0, (int)img.at<uchar>(50, 0));
  549. EXPECT_NE(0, (int)img.at<uchar>(50, 99));
  550. EXPECT_NE(0, (int)img.at<uchar>(99, 50));
  551. }
  552. TEST(Drawing, fillpoly_circle)
  553. {
  554. Mat img_c(640, 480, CV_8UC3, Scalar::all(0));
  555. Mat img_fp = img_c.clone(), img_fcp = img_c.clone(), img_fp3 = img_c.clone();
  556. Point center1(img_c.cols/2, img_c.rows/2);
  557. Point center2(img_c.cols/10, img_c.rows*3/4);
  558. Point center3 = Point(img_c.cols, img_c.rows) - center2;
  559. int radius = img_c.rows/4;
  560. int radius_small = img_c.cols/15;
  561. Scalar color(0, 0, 255);
  562. circle(img_c, center1, radius, color, -1);
  563. // check that circle, fillConvexPoly and fillPoly
  564. // give almost the same result then asked to draw a single circle
  565. vector<Point> vtx;
  566. ellipse2Poly(center1, Size(radius, radius), 0, 0, 360, 1, vtx);
  567. fillConvexPoly(img_fcp, vtx, color);
  568. fillPoly(img_fp, vtx, color);
  569. double diff_fp = cv::norm(img_c, img_fp, NORM_L1)/(255*radius*2*CV_PI);
  570. double diff_fcp = cv::norm(img_c, img_fcp, NORM_L1)/(255*radius*2*CV_PI);
  571. EXPECT_LT(diff_fp, 1.);
  572. EXPECT_LT(diff_fcp, 1.);
  573. // check that fillPoly can draw 3 disjoint circles at once
  574. circle(img_c, center2, radius_small, color, -1);
  575. circle(img_c, center3, radius_small, color, -1);
  576. vector<vector<Point> > vtx3(3);
  577. vtx3[0] = vtx;
  578. ellipse2Poly(center2, Size(radius_small, radius_small), 0, 0, 360, 1, vtx3[1]);
  579. ellipse2Poly(center3, Size(radius_small, radius_small), 0, 0, 360, 1, vtx3[2]);
  580. fillPoly(img_fp3, vtx3, color);
  581. double diff_fp3 = cv::norm(img_c, img_fp3, NORM_L1)/(255*(radius+radius_small*2)*2*CV_PI);
  582. EXPECT_LT(diff_fp3, 1.);
  583. }
  584. }} // namespace