本文首发于“小白学视觉”微信公众号,欢迎关注公众号
本文作者为小白,版权归人民邮电出版社发行所有,禁止转载,侵权必究!
经过几个月的努力,小白终于完成了市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》。为了更让小伙伴更早的了解最新版的OpenCV 4,小白与出版社沟通,提前在公众号上连载部分内容,请持续关注小白。
有时我们关注的区域是一些面积较小数目较多的连通域或者像素点,并且这些区域相对的集中在一起。此时如果寻找轮廓并对每个轮廓进行外接多边形逼近,结果会有较多的多边形。为了避免这个情况,我们可以将这些连通域或者像素点看成一个大的区域,此时我们可以寻找包围将这些区域的规则图形,例如三角形、圆形等,三角形包围2D点集的示意图如图7-27所示。本节将重点介绍如何寻找包围2D点集的规则图形,包括三角形和圆形。OpenCV 4提供了用于寻找包围2D点集的规则图形的函数,接下来将介绍这些函数的函数原型以及使用方法。
OpenCV 4提供了minEnclosingTriangle()函数用于寻找2D点集的最小包围三角形,函数的函数原型在代码清单7-34中给出。
代码清单7-34 minEnclosingTriangle()函数原型
1. double cv::minEnclosingTriangle(InputArray points,
2. OutputArray triangle
3. )
- points:待寻找包围三角形的2D点集。
- triangle:拟合出的三角形三个顶点坐标。
该函数能够找到包含给定2D点集的最小区域的三角形,函数返回值为double类型的三角形面积。函数只有两个参数,第一个参数是待寻找包围三角形的2D点集,2D点可以存放在vector<>或者Mat类型的变量中,数据类型为CV_32S或CV_32F;第二个参数是包含所有2D点的面积最小的三角形的三个顶点坐标,输出的数据类型为CV_32F,存放在vector类型的变量中。该函数的使用方式在代码清单7-36的示例程序中给出。
OpenCV 4还提供了minEnclosingCircle()函数用于寻找2D点集的最小包围圆形,该函数的函数原型在代码清单7-35中给出。
代码清单7-35 minEnclosingCircle()函数原型
1. void cv::minEnclosingCircle(InputArray points,
2. Point2f & center,
3. float & radius
4. )
- points:待寻找包围圆形的2D点集。
- center:圆形的圆心。
- radius:圆形的半径。
该函数使用迭代算法寻找2D点集的最小包围圆形。函数的第一个参数是待寻找包围圆形的2D点集,2D点可以存放在vector<>或者Mat类型的变量中。函数第二个参数和第三个参数分别是2D点集最小包围圆的圆心和半径,圆心的数据类型为Point2f,半径的数据类型为float。该函数的使用方式在代码清单7-36的示例程序中给出。
在代码清单7-36的程序中随机生成100以内的点,并随机分布在图像中的指定区域内,之后通过minEnclosingTriangle()函数和minEnclosingCircle()函数寻找包围这些点的三角形和圆形。为了能够反复的查看结果,程序设置了while循环,直到按下“q”、“Q”或者“ESC”按键时程序跳出循环。程序的运行结果如图7-28所示,由于程序中像素点是随机生成的,因此每次运行结果会有不同。
代码清单7-36 myTriangleAndCircle.cpp点集外包轮廓
1. #include <opencv2opencv.hpp>
2. #include <iostream>
3. #include <vector>
4.
5. using namespace cv;
6. using namespace std;
7.
8. int main()
9. {
10. Mat img(500, 500, CV_8UC3, Scalar::all(0));
11. RNG& rng = theRNG(); //生成随机点
12.
13. while (true)
14. {
15. int i, count = rng.uniform(1, 101);
16. vector<Point> points;
17. //生成随机点
18. for (i = 0; i < count; i++)
19. {
20. Point pt;
21. pt.x = rng.uniform(img.cols / 4, img.cols * 3 / 4);
22. pt.y = rng.uniform(img.rows / 4, img.rows * 3 / 4);
23. points.push_back(pt);
24. }
25.
26. //寻找包围点集的三角形
27. vector<Point2f> triangle;
28. double area = minEnclosingTriangle(points, triangle);
29.
30. //寻找包围点集的圆形
31. Point2f center;
32. float radius = 0;
33. minEnclosingCircle(points, center, radius);
34.
35. //创建两个图片用于输出结果
36. img = Scalar::all(0);
37. Mat img2;
38. img.copyTo(img2);
39.
40. //在图像中绘制坐标点
41. for (i = 0; i < count; i++)
42. {
43. circle(img, points[i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
44. circle(img2, points[i], 3, Scalar(255, 255, 255), FILLED, LINE_AA);
45. }
46.
47. //绘制三角形
48. for (i = 0; i < 3; i++)
49. {
50. if (i==2)
51. {
52. line(img, triangle[i], triangle[0], Scalar(255, 255, 255), 1, 16);
53. break;
54. }
55. line(img, triangle[i], triangle[i + 1], Scalar(255, 255, 255), 1, 16);
56. }
57.
58. //绘制圆形
59. circle(img2, center, cvRound(radius), Scalar(255, 255, 255), 1, LINE_AA);
60.
61. //输出结果
62. imshow("triangle", img);
63. imshow("circle", img2);
64.
65. //按q键或者ESC键退出程序
66. char key = (char)waitKey();
67. if (key == 27 || key == 'q' || key == 'Q')
68. {
69. break;
70. }
71. }
72. return 0;
73. }
经过几个月的努力,市面上第一本OpenCV 4入门书籍《OpenCV 4开发详解》将春节后由人民邮电出版社发行。如果小伙伴觉得内容有帮助,希望到时候多多支持!
关注小白的小伙伴可以提前看到书中的内容,我们创建了学习交流群,欢迎各位小伙伴添加小白微信加入交流群,添加小白时请备注“学习OpenCV 4”。
https://u.wechat.com/MJ-57nVtXgxUyL3dTwWd014 (二维码自动识别)