28、【opencv入门】轮廓查找与绘制(6)——外接圆、椭圆拟合、逼近多边形曲线、计算轮廓面积及长度、提取不规则轮廓 一、轮廓最小外接圆---minEnclosingCircle() 三、逼近多边形曲线---approxPolyDP()  四、计算轮廓面积---contourArea() 六、提取不规则轮廓

1 CV_EXPORTS_W void minEnclosingCircle(InputArray points, CV_OUT Point2f& center, CV_OUT float& radius);

  points: 输入的二维点集, 可以填Mat类型或std::vector

  center: Point2f&类型的center, 圆的输出圆心

  radius: float&类型, 表示圆的输出半径

28、【opencv入门】轮廓查找与绘制(6)——外接圆、椭圆拟合、逼近多边形曲线、计算轮廓面积及长度、提取不规则轮廓
一、轮廓最小外接圆---minEnclosingCircle()
三、逼近多边形曲线---approxPolyDP()
 四、计算轮廓面积---contourArea() 
六、提取不规则轮廓

 1 //最小外接圆
 2 #include "opencv2/opencv.hpp"
 3 #include<iostream>
 4 
 5 using namespace std;
 6 using namespace cv;
 7 
 8 int main() 
 9 {
10     Mat srcImg = imread("1.png");
11     imshow("src", srcImg);
12     Mat dstImg = srcImg.clone();
13     GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
14     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
15     Canny(srcImg, srcImg, 100, 200);
16     imshow("Canny", srcImg);
17 
18     //查找轮廓
19     vector<vector<Point>> contours;
20     vector<Vec4i> hierarcy;
21     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
22     cout << "num=" << contours.size() << endl;
23 
24     Point2f center;  //定义圆中心坐标
25     float radius;  //定义圆半径
26     for (int i = 0; i<contours.size(); i++)  //依次遍历每个轮廓
27     {
28         minEnclosingCircle(Mat(contours[i]), center, radius);
29         drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);
30         circle(dstImg, center, radius, Scalar(0, 255, 0), 2, 8);  //绘制第i个轮廓的最小外接圆
31     }
32     imshow("dst", dstImg);
33 
34     waitKey(0);
35     return 0;
36 }

二、轮廓椭圆拟合---fitEllipse()

1 CV_EXPORTS_W RotatedRect fitElipse(InputArray points);

  points: 输入的二维点集, 可以填Mat类型或std::vector

  返回值: RotatedRect类旋转矩形对象

28、【opencv入门】轮廓查找与绘制(6)——外接圆、椭圆拟合、逼近多边形曲线、计算轮廓面积及长度、提取不规则轮廓
一、轮廓最小外接圆---minEnclosingCircle()
三、逼近多边形曲线---approxPolyDP()
 四、计算轮廓面积---contourArea() 
六、提取不规则轮廓

 1 //轮廓椭圆拟合
 2 #include "opencv2/opencv.hpp"
 3 
 4 using namespace cv;
 5 
 6 int main() 
 7 {
 8     Mat srcImg = imread("1.png");
 9     imshow("src", srcImg);
10     Mat dstImg = srcImg.clone();
11     GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
12     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
13     Canny(srcImg, srcImg, 100, 200);
14     imshow("Canny", srcImg);
15 
16     //查找轮廓
17     vector<vector<Point>> contours;
18     vector<Vec4i> hierarcy;
19     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
20 
21     vector<RotatedRect> box(contours.size());
22     Point2f rect[4];
23     for (int i = 0; i<contours.size(); i++)
24     {
25         box[i] = fitEllipse(Mat(contours[i]));
26         //ellipse(dstImg, box[i].center, Size(box[i].size.width/2, box[i].size.height/2), box[i].angle, 0, 360, Scalar(0, 255, 0), 2, 8);
27         ellipse(dstImg, box[i], Scalar(0, 255, 0), 2, 8);
28     }
29     imshow("dst", dstImg);
30 
31     waitKey(0);
32     return 0;
33 }

三、逼近多边形曲线---approxPolyDP()

1 CV_EXPORTS_W void approxPolyDP(InputArray curve, OutputArray approxCurve, double epsilon, bool closed);

  curve: 输入的二维点集, 可以填Mat类型或std::vector

  approxCurve: 多边形逼近的结果, 其类型和输入二维点集类型一致

  epsilon: 逼近的精度, 为原始曲线和近似曲线间的最大值

  closed: 如果其为真, 则近似的曲线为封闭曲线, 否则近似的曲线不封闭

28、【opencv入门】轮廓查找与绘制(6)——外接圆、椭圆拟合、逼近多边形曲线、计算轮廓面积及长度、提取不规则轮廓
一、轮廓最小外接圆---minEnclosingCircle()
三、逼近多边形曲线---approxPolyDP()
 四、计算轮廓面积---contourArea() 
六、提取不规则轮廓

 1 //逼近多边形曲线
 2 #include "opencv2/opencv.hpp"
 3 using namespace cv;
 4 
 5 int main() 
 6 {
 7     Mat srcImg = imread("2.jpg");
 8     imshow("src", srcImg);
 9     Mat dstImg = srcImg.clone();
10     Mat dstImg2(srcImg.size(), CV_8UC3, Scalar::all(0));//全黑图像
11 
12     GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
13     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
14     //Canny(srcImg, srcImg, 100, 200);
15     threshold(srcImg, srcImg, 200, 255, CV_THRESH_BINARY_INV);
16     imshow("threshold", srcImg);
17 
18     vector<vector<Point>> contours;
19     vector<Vec4i> hierarcy;
20     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
21     vector<vector<Point>> contours_poly(contours.size());
22 
23     for (int i = 0; i<contours.size(); i++)
24     {
25         approxPolyDP(Mat(contours[i]), contours_poly[i],15, true);//true曲线封闭,反之不封闭
26         drawContours(dstImg, contours, i, Scalar(0, 255, 0), 2, 8);//绘制轮廓
27         drawContours(dstImg2, contours_poly, i, Scalar(0, 255, 255), 2, 8);  //绘制多边形逼近
28     }
29     imshow("dst", dstImg);
30     imshow("approx", dstImg2);
31 
32     waitKey(0);
33     return 0;
34 }

 四、计算轮廓面积---contourArea()

1 CV_EXPORTS_W double contourArea(InputArray contour, bool oriented=false);

  contour: 输入的二维点集或轮廓, 可以填Mat类型或std::vector

  oriented: 默认值false, 表示返回面积为绝对值, 负责带符号

  返回值: double类型返回轮廓面积

 五、计算轮廓长度---arcLength()

1 CV_EXPORTS_W double arcLength(InputArray curve, bool closed);

  curve: 输入的二维点集, 可以填Mat类型或std::vector

  colsed: 用于指示曲线是否封闭的标识符, 默认值true, 表示曲线封闭 

  返回值: double类型返回轮廓长度

注:contourArea()&& arcLength()可用于轮廓删选 

 1 //计算轮廓面积和轮廓长度
 2 #include "opencv2/opencv.hpp"
 3 #include<iostream>
 4 
 5 using namespace std;
 6 using namespace cv;
 7 
 8 int main() 
 9 {
10     Mat srcImg = imread("3.jpg");
11     imshow("src", srcImg);
12     Mat dstImg = srcImg.clone();
13     Mat dstImg2(srcImg.size(), CV_8UC3, Scalar::all(0));
14 
15     GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
16     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
17     //Canny(srcImg, srcImg, 100, 200);
18     threshold(srcImg, srcImg, 200, 255, CV_THRESH_BINARY);
19     imshow("threshold", srcImg);
20 
21     vector<vector<Point>> contours;
22     vector<Vec4i> hierarcy;
23     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
24     cout << "num=" << contours.size() << endl;
25 
26     for (int i = 0; i<contours.size(); i++)
27     {
28         double area = contourArea(contours[i]);//计算第i个轮廓的面积
29         cout<<"area--"<<i<<"---"<<area<<endl;
30 
31         double length = arcLength(contours[i], true);
32         cout << "length--" << i << "---" << length << endl;
33         //if(area>10000)  //面积大约1W
34         //if(area> 100 && area<300)
35 
36         if (length<300 && area>300)  
37             drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8);
38     }
39     imshow("dst", dstImg);
40     waitKey(0);
41     return 0;
42 }

六、提取不规则轮廓

 1 //提取不规则轮廓
 2 #include "opencv2/opencv.hpp"
 3 
 4 using namespace cv;
 5 
 6 int main() 
 7 {
 8     Mat srcImg = imread("2.jpg");
 9     imshow("src", srcImg);
10     Mat dstImg = srcImg.clone();  //原图备份
11     Mat tempImg = srcImg.clone();  //原图备份
12     Mat tempImg2(srcImg.size(), CV_8UC3, Scalar::all(0));  //定义全黑的和原图一样大小的图像
13     Mat draw(srcImg.size(), CV_8UC3, Scalar::all(0)); 
14     Mat tempImg3(srcImg.size(), CV_8UC3, Scalar::all(0)); 
15 
16     GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0);
17     cvtColor(srcImg, srcImg, CV_BGR2GRAY);
18     threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化
19     imshow("threshold", srcImg);
20 
21     vector<vector<Point>> contours;
22     vector<Vec4i> hierarcy;
23     findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);
24     while (1)
25     {
26         for (int i = 0; i<contours.size(); i++)
27         {
28             tempImg2.copyTo(draw);  //每次进入将draw清空为全黑
29             tempImg2.copyTo(tempImg3); 
30             //drawContours(dstImg, contours, i, Scalar(0, 255, 0), 5, 8);    
31             drawContours(draw, contours, i, Scalar(255, 255, 255), -1, 8);
32             Mat mask;  //定义掩码
33             cvtColor(draw, mask, CV_BGR2GRAY);
34             tempImg.copyTo(tempImg3, mask);  //将tempImg 复制到tempImg3(只有mask部分被复制)
35             imshow("draw", draw);
36             imshow("result", tempImg3);
37             char key = waitKey();
38             if (key == 27)  //按下Esc键跳出for循环
39                 break;
40         }
41         break;
42     }
43     return 0;
44 }