opencv筛选轮廓的几种方法总结
在使用opencv处理图像的时候,在获取ROI区域这一步用的最多的就是找到指定区域,一般是根据轮廓提取,我们可以通过opencv中的findContours()
函数来查找图片中的轮廓,但是会发现找到的轮廓相当之多,如何在这些轮廓中准确定位道自己需要的轮廓呢?下面介绍几种方法:
前导知识
1. 查找轮廓
findContours() ps:点击函数名可以直接跳转到官方文档哦!
void cv::findContours(InputOutputArray image, OutputArrayOfArrays contours, OutputArray hierarchy, int mode, int method, Point offset = Point() ) Python: cv.findContours(image, mode, method[, contours[, hierarchy[, offset]]])->image, contours, hierarchy
#include <opencv2/imgproc.hpp>
在二值图像中查找轮廓
参数 | 说明 | 可选值 |
---|---|---|
image | 输入的源图像 | |
contours | (out)查找到的所有的轮廓的集合 | |
hierarchy | (out)维护了每个轮廓的拓扑结构(层级关系),和contours同型 | |
mode | 轮廓检索模式 | RETR_EXTERNAL RETR_LIST RETR_CCOMP RETR_TREE RETR_FLOODFILL |
method | 轮廓近似方法 | CHAIN_APPROX_NONE CHAIN_APPROX_SIMPLE CHAIN_APPROX_TC89_L1 CHAIN_APPROX_TC89_KCOS |
offest | 每个轮廓点移动的偏移量 |
Examples:
vector<vector<Point> > contours; vector<Vec4i> hierarchy; cv::findContours( img, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE);
2. 绘制轮廓
drawContours()ps:点击函数名可以直接跳转到官方文档哦!
void cv::drawContours ( InputOutputArray image, InputArrayOfArrays contours, int contourIdx, const Scalar & color, int thickness = 1, int lineType = LINE_8, InputArray hierarchy = noArray(), int maxLevel = INT_MAX, Point offset = Point() ) Python: cv.drawContours(image, contours, contourIdx, color[, thickness[, lineType[, hierarchy[, maxLevel[, offset]]]]])->image
#include <opencv2/imgproc.hpp>
绘制轮廓线或者填充轮廓
参数 | 说明 | 取值 |
---|---|---|
image | 输入的源图像 | |
contours | 保存了所有轮廓的集合 | |
contourIdx | 待绘制的轮廓序号 | |
color | 绘制的轮廓线的颜色 | |
thickness | 轮廓线的粗细 | 负值时绘制内轮廓 |
lineType | 轮廓线线型 | FILLED LINE_4 LINE_8 LINE_AA |
hierarchy | 维护了所有轮廓的拓扑结构 | |
maxLevel | 最大嵌套层级 | |
offset | 轮廓线的偏移量 |
Examples:
vector<vector<Point> > contours; vector<Vec4i> hierarchy; findContours(imgDilate, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE ); for (int idx = 0; idx < contours.size(); idx++) { Scalar color(rand() & 255, rand() & 255, rand() & 255); drawContours(img, contours, idx, color, 2, LINE_8, hierarchy, 3); } imshow("img",img);
正文
1. 根据面积筛选
使用contourArea()
可以计算得到一个轮廓的面积(这里的面积的单位应该是平方像素),然后和最小面积比较,得到筛选后的轮廓。


Examples:
// 计算轮廓面积 double area = contourArea(contours[idx]); // 预设最小轮廓面积为1000,<=1000的轮廓被筛除,>1000的轮廓被放入finalContours中以返回 if(area > minArea){ finalContours.push_back(contours[idx]); }
2. 根据拐点个数筛选多边形轮廓
如果要在一堆多边形轮廓中筛选出四边形轮廓,则可以首先根据拐点的个数进行筛选,使用approxPolyDP()
获取轮廓拐点。


Examples:
// 获取轮廓拐点,拐点坐标保存在approx中,精度为轮廓周长的0.02倍 approxPolyDP(contours[idx],approx,0.02*arcLength(contours[idx],true), true); // 预设要筛选的拐点数目approxNum=4 if (approx.size() == approxNum) { finalContours.push_back(contours[idx]); }
3. 根据嵌套层级筛选
以上面的二值图像为例,如果当通过拐点、面积筛选的方法筛选之后,发现白线的内侧和外侧轮廓都被画了出来,如果只要外轮廓,则可以根据hierarchy
来进行筛选。


approxPolyDP(contours[idx], approx, 0.02 * arcLength(contours[idx], true), true); // 根据拐点数量筛选 if (approx.size() == approxNum) { // 筛除具有父轮廓的轮廓 if (hierarchy[idx][3] < 0) { dstContours.push_back(contours[idx]); dstApproxs.push_back(approx); } }
参考文献
杂项
资源分享
本文作者:Free152
本文链接:https://www.cnblogs.com/free152/p/16868637.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步