一、轮廓最小外接圆---minEnclosingCircle()
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&类型, 表示圆的输出半径
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类旋转矩形对象
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: 如果其为真, 则近似的曲线为封闭曲线, 否则近似的曲线不封闭
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 }