轮廓特征属性及应用(六)
1.轮廓最小外接圆——minEnclosingCircle()
2.轮廓的椭圆拟合——fitEllipse()
3.轮廓的多边形逼近——approxPolyDP()
4.计算轮廓面积——contourArea();计算轮廓长度——arcLength()
5.提取不规则轮廓
先上ppt:
代码:1.轮廓最小外接圆
///轮廓最小外接圆
#include "opencv2/opencv.hpp"
using namespace cv;
#include <iostream>
using namespace std;
int main()
{
//1.查找轮廓的预处理
Mat srcImg = imread("10.png",CV_LOAD_IMAGE_COLOR);
Mat copyImg = srcImg.clone();
cvtColor(srcImg,srcImg,CV_BGR2GRAY);
threshold(srcImg,srcImg,100,255,CV_THRESH_BINARY);
imshow("threshold",srcImg);
//2.查找轮廓并绘制所有轮廓
vector < vector<Point> > contours;
findContours(srcImg,contours,CV_RETR_EXTERNAL,CV_CHAIN_APPROX_NONE);//最外层轮廓
drawContours(copyImg,contours,-1,Scalar(0,0,255),2,8);
//3.查找最小外接圆
Point2f center;//存储最小外接圆的圆心
float radius;//存储最小外接圆的半径
for (int i = 0; i < contours.size();i++)//遍历每个轮廓
{
minEnclosingCircle(contours[i],center,radius);//查找最小外接圆
circle(copyImg,center,radius,Scalar(255,0,0),2,8);//用circle方法绘制最小外接圆
}
imshow("minEnclosingCircle", copyImg);
waitKey(0);
return 0;
}
运行结果:
代码:2.轮廓的椭圆拟合
///轮廓的椭圆拟合
#include "opencv2/opencv.hpp"
using namespace cv;
#include <iostream>
using namespace std;
int main()
{
//1.查找轮廓的预处理
Mat srcImg = imread("10.png", CV_LOAD_IMAGE_COLOR);
Mat copyImg = srcImg.clone();
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);
imshow("threshold", srcImg);
//2.查找轮廓并绘制所有轮廓
vector < vector<Point> > contours;
findContours(srcImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//最外层轮廓
drawContours(copyImg, contours, -1, Scalar(0, 0, 255), 2, 8);
//3.进行轮廓的椭圆拟合
RotatedRect roRect;//旋转矩形变量,来接收椭圆拟合函数的返回值
for (int i = 0; i < contours.size(); i++)//遍历每个轮廓
{
roRect=fitEllipse(contours[i]);//进行椭圆拟合
ellipse(copyImg,roRect,Scalar(255,0,0),2,8);//用ellipse()方法绘制椭圆,可用旋转矩形直接绘制
}
imshow("fitEllipse", copyImg);
waitKey(0);
return 0;
}
运行结果:
代码:3.轮廓的多边形逼近
///轮廓的多边形逼近
#include "opencv2/opencv.hpp"
using namespace cv;
#include <iostream>
using namespace std;
int main()
{
//1.查找轮廓的预处理
Mat srcImg = imread("02.jpg", CV_LOAD_IMAGE_COLOR);
Mat copyImg = srcImg.clone();
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 200, 255, CV_THRESH_BINARY_INV);
imshow("threshold", srcImg);
//2.查找轮廓并绘制所有轮廓
vector < vector<Point> > contours;
findContours(srcImg, contours, CV_RETR_LIST, CV_CHAIN_APPROX_NONE);//所有轮廓
drawContours(copyImg, contours, -1, Scalar(0, 0, 255), 2, 8);
//3.进行轮廓的多边形逼近
vector<vector<Point>> approxCurve(contours.size());//存储轮廓的多边形逼近的结果
Mat drawImg(srcImg.size(), CV_8UC3, Scalar(0,0,0));//定义一个纯黑的图像,来画上轮廓的多边形逼近
for (int i = 0; i < contours.size(); i++)//遍历每个轮廓
{
approxPolyDP(contours[i],approxCurve[i],4,true);//轮廓的多边形逼近
drawContours(drawImg, approxCurve, i, Scalar(0, 0, 255), 2, 8);//在drawImg上绘制轮廓的多边形逼近
}
imshow("approxPolyDP", drawImg);
waitKey(0);
return 0;
}
运行结果:
代码:4.计算轮廓面积和长度
///计算轮廓面积和长度
#include "opencv2/opencv.hpp"
using namespace cv;
#include <iostream>
using namespace std;
int main()
{
//1.查找轮廓的预处理
Mat srcImg = imread("10.png", CV_LOAD_IMAGE_COLOR);
Mat copyImg = srcImg.clone();
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY);//确保黑中找白
imshow("threshold", srcImg);
//2.查找轮廓并绘制所有轮廓
vector < vector<Point> > contours;
findContours(srcImg, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE);//最外层轮廓
drawContours(copyImg, contours, -1, Scalar(0, 0, 255), 2, 8);
//3.输出每个轮廓的面积和长度
double area;
double length;
for (int i = 0; i < contours.size(); i++)//遍历每个轮廓
{
area = contourArea(contours[i]);//计算轮廓面积
length = arcLength(contours[i],true);//计算曲线或轮廓的周长,当bool变量closed为true时计算轮廓周长
cout << "contour: " << i << " area: " << area << " perimeter: " << length << endl;
}
imshow("contours", copyImg);
waitKey(0);
return 0;
}
运行结果:
代码:5.提取不规则轮廓
///提取不规则轮廓
#include "opencv2/opencv.hpp"
using namespace cv;
#include <iostream>
using namespace std;
int main()
{
//1.查找轮廓的预处理
Mat srcImg = imread("220.jpg", CV_LOAD_IMAGE_COLOR);
Mat copyImg = srcImg.clone();
GaussianBlur(srcImg,srcImg,Size(5,5),0,0);//高斯滤波,滤去噪声
cvtColor(srcImg, srcImg, CV_BGR2GRAY);
threshold(srcImg, srcImg, 100, 255, CV_THRESH_BINARY_INV);//确保黑中找白
imshow("threshold", srcImg);
//2.查找轮廓
vector < vector<Point> > contours;
findContours(srcImg, contours, CV_RETR_TREE, CV_CHAIN_APPROX_NONE);//所有轮廓
//3.遍历轮廓,找出正外接矩形
Mat mask = Mat::zeros(srcImg.size(),CV_8UC3);//同原图一样大小,纯黑的mask图像
Mat draw = Mat::zeros(srcImg.size(), CV_8UC3);//将原图copyTo到draw上,加上mask操作
Mat temp = Mat::zeros(srcImg.size(), CV_8UC3);//每次循环,重置mask和draw
Rect boundRect;//存储轮廓的正外接矩形
for (int i = 0; i < contours.size(); i++)//遍历每个轮廓
{
temp.copyTo(mask);//重置mask
temp.copyTo(draw);//重置draw
drawContours(mask,contours,i,Scalar(255,255,255),-1);//在mask上用白色绘制轮廓,-1向内填充
imshow("mask",mask);
cvWaitKey(0);//等待按键
boundRect=boundingRect(contours[i]);//获得第i个轮廓的正外接矩形
copyImg.copyTo(draw,mask);//将原图copyTo到draw上,加上mask操作
imshow("draw", draw);
Mat ROI = draw(boundRect);//定义ROI,即为draw上的boundRect区域
char name[20] = { 0 };
sprintf(name,"E:\\temp\\%d.jpg",i);//格式化ROI文件名
imwrite(name,ROI);//写ROI到本地
}
waitKey(0);
return 0;
}
运行结果: