opencv学习之路(27)、轮廓查找与绘制(六)——外接圆、椭圆拟合、逼近多边形曲线、计算轮廓面积及长度、提取不规则轮廓
一、最小外接圆
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 using namespace std; 4 using namespace cv; 5 6 void main() { 7 Mat srcImg = imread("E://10.png"); 8 imshow("src", srcImg); 9 Mat dstImg = srcImg.clone(); 10 GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0); 11 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 12 Canny(srcImg, srcImg, 100, 200); 13 imshow("Canny", srcImg); 14 15 //查找轮廓 16 vector<vector<Point>> contours; 17 vector<Vec4i> hierarcy; 18 findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 19 cout << "num=" << contours.size() << endl; 20 21 Point2f center; //定义圆中心坐标 22 float radius; //定义圆半径 23 for (int i = 0; i<contours.size(); i++) //依次遍历每个轮廓 24 { 25 minEnclosingCircle(Mat(contours[i]), center, radius); 26 drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8); 27 circle(dstImg, center, radius, Scalar(0, 255, 0), 2, 8); //绘制第i个轮廓的最小外接圆 28 } 29 imshow("dst", dstImg); 30 31 waitKey(0); 32 }
二、椭圆拟合
1 #include "opencv2/opencv.hpp" 2 using namespace cv; 3 4 void main() { 5 Mat srcImg = imread("E://10.png"); 6 imshow("src", srcImg); 7 Mat dstImg = srcImg.clone(); 8 GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0); 9 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 10 Canny(srcImg, srcImg, 100, 200); 11 imshow("Canny", srcImg); 12 13 //查找轮廓 14 vector<vector<Point>> contours; 15 vector<Vec4i> hierarcy; 16 findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 17 18 vector<RotatedRect> box(contours.size()); 19 Point2f rect[4]; 20 for (int i = 0; i<contours.size(); i++) 21 { 22 box[i] = fitEllipse(Mat(contours[i])); 23 //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); 24 ellipse(dstImg, box[i], Scalar(0, 255, 0), 2, 8); 25 } 26 imshow("dst", dstImg); 27 28 waitKey(0); 29 }
三、逼近多边形曲线
1 #include "opencv2/opencv.hpp" 2 using namespace cv; 3 4 void main() { 5 Mat srcImg = imread("E://02.jpg"); 6 imshow("src", srcImg); 7 Mat dstImg = srcImg.clone(); 8 Mat dstImg2(srcImg.size(), CV_8UC3, Scalar::all(0));//全黑图像 9 10 GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0); 11 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 12 //Canny(srcImg, srcImg, 100, 200); 13 threshold(srcImg, srcImg, 200, 255, CV_THRESH_BINARY_INV); 14 imshow("threshold", srcImg); 15 16 vector<vector<Point>> contours; 17 vector<Vec4i> hierarcy; 18 findContours(srcImg, contours, hierarcy, CV_RETR_TREE, CV_CHAIN_APPROX_NONE); 19 vector<vector<Point>> contours_poly(contours.size()); 20 21 for (int i = 0; i<contours.size(); i++) 22 { 23 approxPolyDP(Mat(contours[i]), contours_poly[i],15, true);//true曲线封闭,反之不封闭 24 drawContours(dstImg, contours, i, Scalar(0, 255, 0), 2, 8);//绘制轮廓 25 drawContours(dstImg2, contours_poly, i, Scalar(0, 255, 255), 2, 8); //绘制多边形逼近 26 } 27 imshow("dst", dstImg); 28 imshow("approx", dstImg2); 29 30 waitKey(0); 31 }
四、计算轮廓面积及长度(可用于轮廓筛选)
1 #include "opencv2/opencv.hpp" 2 #include<iostream> 3 using namespace std; 4 using namespace cv; 5 6 void main() { 7 Mat srcImg = imread("E://33.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); 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 cout << "num=" << contours.size() << endl; 22 23 for (int i = 0; i<contours.size(); i++) 24 { 25 double area = contourArea(contours[i]);//计算第i个轮廓的面积 26 cout<<"area--"<<i<<"---"<<area<<endl; 27 28 double length = arcLength(contours[i], true); 29 cout << "length--" << i << "---" << length << endl; 30 //if(area>10000) //面积大约1W 31 //if(area> 100 && area<300) 32 33 if (length<300 && area>300) 34 drawContours(dstImg, contours, i, Scalar(0, 0, 255), 2, 8); 35 } 36 imshow("dst", dstImg); 37 waitKey(0); 38 }
五、提取不规则轮廓
1 #include "opencv2/opencv.hpp" 2 using namespace cv; 3 4 void main() { 5 Mat srcImg = imread("E://220.jpg"); 6 imshow("src", srcImg); 7 Mat dstImg = srcImg.clone(); //原图备份 8 Mat tempImg = srcImg.clone(); //原图备份 9 Mat tempImg2(srcImg.size(), CV_8UC3, Scalar::all(0)); //定义全黑的和原图一样大小的图像 10 Mat draw(srcImg.size(), CV_8UC3, Scalar::all(0)); 11 Mat tempImg3(srcImg.size(), CV_8UC3, Scalar::all(0)); 12 13 GaussianBlur(srcImg, srcImg, Size(3, 3), 0, 0); 14 cvtColor(srcImg, srcImg, CV_BGR2GRAY); 15 threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY); //二值化 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 while (1) 22 { 23 for (int i = 0; i<contours.size(); i++) 24 { 25 tempImg2.copyTo(draw); //每次进入将draw清空为全黑 26 tempImg2.copyTo(tempImg3); 27 //drawContours(dstImg, contours, i, Scalar(0, 255, 0), 5, 8); 28 drawContours(draw, contours, i, Scalar(255, 255, 255), -1, 8); 29 Mat mask; //定义掩码 30 cvtColor(draw, mask, CV_BGR2GRAY); 31 tempImg.copyTo(tempImg3, mask); //将tempImg 复制到tempImg3(只有mask部分被复制) 32 imshow("draw", draw); 33 imshow("result", tempImg3); 34 char key = waitKey(); 35 if (key == 27) //按下Esc键跳出for循环 36 break; 37 } 38 break; 39 } 40 }