一、概述
案例:使用OpenCV的findContours发现轮廓并根据轮廓的面积过滤轮廓。
发现轮廓函数:
发现轮廓:
findContours(
InputOutputArray binImg, // 输入图像,非0的像素被看成1,0的像素值保持不变,8-bit
OutputArrayOfArrays contours,// 全部发现的轮廓对象
OutputArray, hierachy// 图该的拓扑结构,可选,该轮廓发现算法正是基于图像拓扑结构实现。
int mode, // 轮廓返回的模式
int method,// 发现方法
Point offset=Point()// 轮廓像素的位移,默认(0, 0)没有位移
)
返回轮廓的模式:
取值一:RETR_EXTERNAL只检测最外围轮廓,包含在外围轮廓内的内围轮廓被忽略
取值二:RETR_LIST 检测所有的轮廓,包括内围、外围轮廓,但是检测到的轮廓不建立等级关系,彼此之间独立,没有等级关系,这就意味着这个检索模式下不存在父轮廓或内嵌轮廓,
所以hierarchy向量内所有元素的第3、第4个分量都会被置为-1,具体下文会讲到
取值三:RETR_CCOMP 检测所有的轮廓,但所有轮廓只建立两个等级关系,外围为顶层,若外围内的内围轮廓还包含了其他的轮廓信息,则内围内的所有轮廓均归属于顶层
取值四:RETR_TREE, 检测所有轮廓,所有轮廓建立一个等级树结构。外层轮廓包含内层轮廓,内层轮廓还可以继续包含内嵌轮廓。
定义轮廓的搜索模式:
取值一:CHAIN_APPROX_NONE 保存物体边界上所有连续的轮廓点到contours向量内
取值二:CHAIN_APPROX_SIMPLE 仅保存轮廓的拐点信息,把所有轮廓拐点处的点保存入contours向量内,拐点与拐点之间直线段上的信息点不予保留
取值三和四:CHAIN_APPROX_TC89_L1,CHAIN_APPROX_TC89_KCOS使用teh-Chinl chain 近似算法
drawContours(
InputOutputArray binImg, // 输出图像
OutputArrayOfArrays contours,// 全部发现的轮廓对象
Int contourIdx// 轮廓索引号
const Scalar & color,// 绘制时候颜色
int thickness,// 绘制线宽
int lineType ,// 线的类型LINE_8
InputArray hierarchy,// 拓扑结构图
int maxlevel,// 最大层数, 0只绘制当前的,1表示绘制绘制当前及其内嵌的轮廓
Point offset=Point()// 轮廓位移,可选
发现轮廓步骤:
1.加载图像
2.将图像转为灰度图
3.执行边缘检测
4.执行轮廓发现
5.绘制轮廓
6.显示绘制后的图片
二、代码示例
Mat src = imread(filePath);
if(src.empty()){
return;
}
imshow("src",src);
Mat gray;
cvtColor(src,gray,COLOR_BGR2GRAY);
imshow("gray",gray);
//执行边缘 检测
Canny(gray,gray,50,100,3,false);
imshow("canny",gray);
//发现轮廓
vector<vector<Point>> contours;
vector<Vec4i> hierarchy;
findContours(gray,contours,hierarchy,RETR_TREE,CHAIN_APPROX_SIMPLE,Point(0,0));
//绘制轮廓
RNG rng;
Mat drawImg=Mat::zeros(gray.size(),CV_8UC3);
for(int i=0;i<contours.size();i++){
double area = contourArea(contours[i],false);
if(area>100){//根据轮廓的面积过滤不需要的轮廓
Scalar color = Scalar(rng.uniform(0,255),rng.uniform(0,255),rng.uniform(0,255));
drawContours(drawImg,contours,i,color,2,LINE_8,hierarchy,0,Point(0,0));
}
}
imshow("drawImg",drawImg);
三、演示图片