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()可以计算得到一个轮廓的面积(这里的面积的单位应该是平方像素),然后和最小面积比较,得到筛选后的轮廓。

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

ps:左图为经过预处理的二值图像,右图为根据拐点数量筛选出的所有拐点为4的轮廓
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来进行筛选。

ps:左图为筛选前,右图为筛选后
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);
}
}
参考文献
杂项
资源分享
opencv筛选轮廓的几种方法总结的更多相关文章
- Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解
Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...
- opencv图像阈值设置的三种方法
1.简单阈值设置 像素值高于阈值时,给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色).这个函数就是 cv2.threshhold().这个函数的第一个参数就是原图像 ...
- jquery遍历筛选数组的几种方法和遍历解析json对象
jquery grep()筛选遍历数组 $().ready( function(){ var array = [1,2,3,4,5,6,7,8,9]; var fil ...
- 相机标定 matlab opencv ROS三种方法标定步骤(1)
一 . 理解摄像机模型,网上有很多讲解的十分详细,在这里我只是记录我的整合出来的资料和我的部分理解 计算机视觉领域中常见的三个坐标系:图像坐标系,相机坐标系,世界坐标系,实际上就是要用矩阵来表 示各个 ...
- 在linux环境下编译运行OpenCV程序的两种方法
原来以为在Ubuntu下安装好了OpenCV之后,自己写个简单的程序应该很容易吧,但是呢,就是为了编译一个简单的显示图片的程序我都快被弄崩溃了. 在谷歌和上StackOverFlow查看相关问题解答之 ...
- opencv 3.1.0 访问像素值的三种方法(C++)
三种方法分别问: 指针访问:void colorReduce_ptr(cv::Mat &inputImage, cv::Mat &outputImage, int div); 迭代器访 ...
- 海康威视采集卡结合opencv使用(两种方法)-转
(注:第一种方法是我的原创 ^_^. 第二种方法是从网上学习的.) 第一种方法:利用 板卡的API: GetJpegImage 得到 Jpeg 格式的图像数据,然后用opencv里的一个函数进行解码 ...
- OpenCV坐标系与操作像素的四种方法
像素是图像的基本组成单位,熟悉了如何操作像素,就能更好的理解对图像的各种处理变换的实现方式了. 1.at方法 第一种操作像素的方法是使用"at",如一幅3通道的彩色图像image的 ...
- OpenCV图像轮廓检测
轮廓检测: 轮廓检测的原理通俗的说就是掏空内部点,比如原图中有3*3的矩形点.那么就可以将中间的那一点去掉. 一.关键函数1.1 cvFindContours函数功能:对图像进行轮廓检测,这个函数将 ...
- 学习opencv跟轮廓相关的
查找轮廓 轮廓到底是什么?一个轮廓一般对应一系列的点,也就是图像中的一条曲线.表示的方法可能根据不同情况而有所不同.有多重方法可以表示曲线.在openCV中一般用序列来存储轮廓信息.序列中的每一个元素 ...
随机推荐
- C#定时任务(Timer)
新建Timer类 using BaseAsset.Data.Infrastructure; using BaseAsset.Data.Repositories; using BaseAsset.Ent ...
- locust socektio协议压测
# -*-coding:UTF-8 -*- from locust import HttpLocust, TaskSet, task, TaskSequence, Locust, events imp ...
- WAP-2.1
WAP 是一种源代码静态分析和数据挖掘工具,用于检测和纠正用 PHP 4.0 或更高版本编写的 Web 应用程序中的输入验证漏洞,且误报率较低. WAP 检测并纠正以下漏洞: SQL Injectio ...
- matlab 求解 f(x)=x(x+1)(x+2)(x+3)(x+4)...(x+n-2)(x+n-1)(x+n)的导数;
matlab 求解 f(x)=x(x+1)(x+2)(x+3)(x+4)...(x+n-2)(x+n-1)(x+n)的导数; matlab diff() 问题的提出 问题 代码求解 clc; clea ...
- Docker基本命令之 镜像管理
镜像管理 docker常用基础命令: 查看docker版本信息:docker version 查看docker系统信息:docker info docker服务相关: 查看docker服务:syste ...
- jquery.easyui.min.js:12401 Uncaught TypeError: Cannot read property 'combo' of undefined jquery.easyui.min.js:12401
踩坑中成长! jquery1.4.1升级到1.4.3 点击添加报错. 一步步调试js,发现是combox使用问题. 前端报错,未声明,js是easyui的所以只有jsp和js用法问题.看了官方用法,瞬 ...
- c# 串口 转发到 TCP 客户端
前言 对于数据流Stream的转发.在.net 3.5之后的版本只需要 stream.CopyTo(stream). 目前只是为了方便调用测试,花了一点点时间做了一个简单的调用demo 完整代码 us ...
- element-ui跨行
1 <template> 2 <el-table :data="scheduleList" :span-method="objectSpanMethod ...
- elelment中el-cascader怎样自定义显示的lable 与value
1.后端返回的数据类型 2.页面代码 3.重点在于 :props="{ value: 'id',label: 'className',children: 'childNode'}" ...
- Python在字典中通过键名查找键值
def find(target, dict_data): """ :param target: 需要查找的键名 :param dict_data: 需要查找的列表 :re ...