pproxPolyDP 主要功能是把一个连续光滑曲线折线化,对图像轮廓点进行多边形拟合。
原理图:对比之前黑点连线,之后蓝色连线:
C++: void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed)
参数详解;
InputArray curve:一般是由图像的轮廓点组成的点集
OutputArray approxCurve:表示输出的多边形点集
double epsilon:主要表示输出的精度,就是另个轮廓点之间最大距离数,5,6,7,,8,,,,,
bool closed:表示输出的多边形是否封闭
1 #include <opencv2/opencv.hpp>
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <iostream>
5
6
7 using namespace cv;
8 using namespace std;
9
10
11 int main(int argc, char** argv)
12 {
13 Mat img = imread("4.jpg", -1);
14 pyrDown(img, img, Size(img.cols/2, img.rows/2), 4);
15 imshow("img", img);imwrite("img.jpg", img);
16
17 //通过canny算法找轮廓,这样 findcontours 的结果会好些
18 Mat canny_out;
19 Canny(img, canny_out, 45, 127, 3, false);
20 imshow("canny_out", canny_out);imwrite("canny_out.jpg", canny_out);
21
22 //寻找轮廓
23 vector<vector<Point>> contours;
24 vector<Vec4i> hierachy;
25 findContours(canny_out, contours, hierachy, RETR_TREE, CV_CHAIN_APPROX_SIMPLE, Point(-1,-1));
26 drawContours(img, contours, -1, Scalar(0,0,255), 1, 8, hierachy);
27
28 //定义圆形、方形、旋转矩形、椭圆的存储容器
29 vector<vector<Point>> contours_ploy(contours.size());
30 vector<Rect> rects_ploy(contours.size());
31 vector<Point2f> circle_centers(contours.size());
32 vector<float> circle_radius(contours.size());
33 vector<RotatedRect> RotatedRect_ploy;//注意:由于下面赋值的过程中有个点数大于5的条件,所以这里没有直接初始化,才有下面pushback的方法添加值。
34 vector<RotatedRect> ellipse_ploy;//注意,这里是画椭圆,但是容器类型是 RotatedRect
35
36 //将结果放到各自的容器中
37 for (size_t i = 0; i< contours.size(); i++)
38 {
39 approxPolyDP(contours[i], contours_ploy[i], 5, true);
40 rects_ploy[i] = boundingRect(contours_ploy[i]);
41 minEnclosingCircle(contours_ploy[i], circle_centers[i], circle_radius[i]);
42
43 if (contours_ploy[i].size() >5)
44 {
45 RotatedRect temp1 = minAreaRect(contours_ploy[i]);
46 RotatedRect_ploy.push_back(temp1);
47
48 RotatedRect temp2 = fitEllipse(contours_ploy[i]);
49 ellipse_ploy.push_back(temp2);
50 }
51 }
52
53 //定义最终绘图的图片
54 Mat draw_rect(img.size(), img.type(), Scalar::all(0)),
55 draw_rotateRect(img.size(), img.type(), Scalar::all(0)),
56 draw_circle(img.size(), img.type(), Scalar::all(0)),
57 draw_ellipse(img.size(), img.type(), Scalar::all(0));
58
59 //绘图圆形、矩形
60 RNG rng(12345);
61 for (size_t i = 0; i<contours.size(); i++)
62 {
63 Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255));
64 rectangle(draw_rect, rects_ploy[i], color, 1, 8);
65 circle(draw_circle, circle_centers[i], circle_radius[i], color, 1, 8);
66 }
67 imshow("draw_rect", draw_rect);imwrite("draw_rect.jpg", draw_rect);
68 imshow("draw_circle", draw_circle);imwrite("draw_circle.jpg", draw_circle);
69
70 //绘图椭圆形、旋转矩形
71 Point2f pot[4];
72 for (size_t i = 0; i<ellipse_ploy.size(); i++)
73 {
74 Scalar color = Scalar(rng.uniform(0,255), rng.uniform(0,255), rng.uniform(0,255));
75 ellipse(draw_ellipse, ellipse_ploy[i], color, 1, 8);
76
77 RotatedRect_ploy[i].points(pot);
78 for(int j=0; j<4; j++)
79 {
80 line(draw_rotateRect, pot[j], pot[(j+1)%4], color);
81 }
82 }
83 imshow("draw_ellipse", draw_ellipse);imwrite("draw_ellipse.jpg", draw_ellipse);
84 imshow("draw_rotateRect", draw_rotateRect);imwrite("draw_rotateRect.jpg", draw_rotateRect);
85
86
87 waitKey();
88 return 1;
89 }