一、概述
案例:使用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);
三、演示图片