参考网址: findContours函数参数详解
一. 寻找轮廓:findContours函数
1、原型:
findContours( InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset=Point());
参数讲解:
- 第一个参数:image。
- 输入图像,填Mat类对象即可,且需为8位单通道图像。
- 可以是灰度图,更常用的是二值图像。
- 一般是经过Canny、拉普拉斯等边缘检测算子处理过的二值图像;
- 第二个参数:contours。
- 定义为
vector<vector<Point>> contours
- 是一个向量,并且是一个双重向量。向量内每个元素保存了一组由连续的Point点构成的点的集合的向量,每一组Point点集就是一个轮廓。
- 有多少轮廓,向量contours就有多少元素。
- 定义为
- 第三个参数:hierarchy。
- 定义为
vector<Vec4i> hierarchy
- Vec4i的定义:
typedef Vec<int, 4> Vec4i;
Vec4i是Vec<int,4>
的别名。所以从定义上看,hierarchy也是一个向量,向量内每个元素保存了一个包含4个int整型的数组。 - hierarchy向量包含轮廓之间的拓扑信息。每个轮廓contours[i]对应4个hierarchy元素hierarchy[i][0] ~hierarchy[i][3],分别表示第 i个轮廓的后一个轮廓、前一个轮廓、父轮廓、内嵌轮廓的索引编号。如果没有对应项,对应的hierarchy[i]值设置为负数,默认值-1。
- 定义为
第四个参数:int型的mode,定义轮廓的检索模式:
第五个参数:int型的method,定义轮廓的近似方法:
第六个参数:Point偏移量,每个轮廓点相对于原始图像对应点的偏移量。
- 相当于在每一个检测出的轮廓点上加上该偏移量
- 默认值为Point()
- Point可以是负值。
2、参考代码:
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
using namespace cv;
int main(int argc,char *argv[])
{
Mat imageSource=imread(argv[1],0);
imshow("Source Image",imageSource);
Mat image;
GaussianBlur(imageSource,image,Size(3,3),0);
Canny(image,image,100,250);
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(image,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point());
Mat imageContours=Mat::zeros(image.size(),CV_8UC1);
Mat Contours=Mat::zeros(image.size(),CV_8UC1); //绘制
for(int i=0;i<contours.size();i++)
{
//contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
for(int j=0;j<contours[i].size();j++)
{
//绘制出contours向量内所有的像素点
Point P=Point(contours[i][j].x,contours[i][j].y);
Contours.at<uchar>(P)=255;
}
//输出hierarchy向量内容
char ch[256];
sprintf(ch,"%d",i);
string str=ch;
cout<<"向量hierarchy的第" <<str<<" 个元素内容为:"<<endl<<hierarchy[i]<<endl<<endl;
//绘制轮廓
drawContours(imageContours,contours,i,Scalar(255),1,8,hierarchy);
}
imshow("Contours Image",imageContours); //轮廓
imshow("Point of Contours",Contours); //向量contours内保存的所有轮廓点集
waitKey(0);
return 0;
}
二.寻找凸包:convexHull()函数
1、函数原型:
void convexHull( InputArray points, OutputArray hull, bool clockwise = false, bool returnPoints = true );
参数就是之前计算出的轮廓和用于输出的集合。可以参见《OpenCV3编程入门》第313页。
2、参考代码(找出最外圈轮廓,并寻找凸包,绘制轮廓与凸包):
#include <iostream>
#include <opencv2/opencv.hpp>
using namespace std;
int main()
{
Mat inImg = imread("F:/test_photo/luanphoto10.png", 0);
imshow("input image", inImg);
Mat inImgTemp = inImg.clone();
GaussianBlur(inImgTemp, inImgTemp, Size(3, 3), 0);
Canny(inImgTemp, inImgTemp, 100, 250);
vector<vector<Point>> contours;
findContours(inImgTemp, contours, CV_RETR_EXTERNAL, CV_CHAIN_APPROX_NONE, Point());
Mat imageContours = Mat::zeros(inImgTemp.size(), CV_8UC1);
Mat Contours = Mat::zeros(inImgTemp.size(), CV_8UC1); //绘制
for (int i = 0; i<contours.size(); i++)
{
//contours[i]代表的是第i个轮廓,contours[i].size()代表的是第i个轮廓上所有的像素点数
for (int j = 0; j<contours[i].size(); j++)
{
//绘制出contours向量内所有的像素点
Point P = Point(contours[i][j].x, contours[i][j].y);
Contours.at<uchar>(P) = 255;
}
//绘制轮廓
drawContours(imageContours, contours, i, Scalar(255), FILLED, 8);
}
// 遍历每个轮廓,寻找其凸包
vector<vector<Point> >hull(contours.size());
for (unsigned int i = 0; i < contours.size(); i++)
{
convexHull(Mat(contours[i]), hull[i], false);
}
// 绘出轮廓及其凸包
Mat drawing = Mat::zeros(inImgTemp.size(), CV_8UC3);
for (unsigned int i = 0; i< contours.size(); i++)
{
Scalar color = Scalar(0, 0, 255);
drawContours(drawing, contours, i, color, FILLED, 8, vector<Vec4i>(), 0, Point());
drawContours(drawing, hull, i, color, FILLED, 8, vector<Vec4i>(), 0, Point());
}
imshow("Contours Image", imageContours); //轮廓
imshow("Point of Contours", Contours); //向量contours内保存的所有轮廓点集
// 显示效果图
imshow("drawing", drawing);
waitKey(0);
return 0;
}
三. 绘制轮廓:drawContours()函数
1、函数的调用形式:
void drawContours(InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar& color, int thickness=1, int lineType=8, InputArray hierarchy=noArray(), int maxLevel=INT_MAX, Point offset=Point() )
函数参数详解:
- 第一个参数image:目标图像
- 第二个参数contours:输入的轮廓组,每一组轮廓由点vector构成
- 第三个参数contourIdx:指明画第几个轮廓,如果该参数为负值,则画全部轮廓
- 第四个参数color:为轮廓的颜色
- 第五个参数thickness:为轮廓的线宽,默认值为1
- 如果为负值 或 FILLED 表示填充轮廓内部
- 第六个参数lineType:线型,默认值为8
- 第七个参数hierarchy:为轮廓结构信息
- 第八个参数maxLevel:用于绘制轮廓的最大等级,有默认值INT_MAX
- 第九个参数offset:可选的轮廓偏移参数,有默认值Point()。