在使用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);
}
}

参考文献

  1. OpenCV—轮廓操作一站式详解:查找/筛选/绘制/形状描述与重心标注(Python版)
  2. OpenCV官方文档

杂项

  1. 如何阅读OpenCV官方文档
  2. markdown更改颜色和字体
  3. markdown设置图片大小

资源分享

  1. opencv官方文档网盘下载

opencv筛选轮廓的几种方法总结的更多相关文章

  1. Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解

    Jquery遍历筛选数组的几种方法和遍历解析json对象|Map()方法详解 一.Jquery遍历筛选数组 1.jquery grep()筛选遍历数组 $().ready( function(){ v ...

  2. opencv图像阈值设置的三种方法

    1.简单阈值设置   像素值高于阈值时,给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色).这个函数就是 cv2.threshhold().这个函数的第一个参数就是原图像 ...

  3. jquery遍历筛选数组的几种方法和遍历解析json对象

    jquery grep()筛选遍历数组 $().ready(    function(){        var array = [1,2,3,4,5,6,7,8,9];        var fil ...

  4. 相机标定 matlab opencv ROS三种方法标定步骤(1)

    一 . 理解摄像机模型,网上有很多讲解的十分详细,在这里我只是记录我的整合出来的资料和我的部分理解 计算机视觉领域中常见的三个坐标系:图像坐标系,相机坐标系,世界坐标系,实际上就是要用矩阵来表 示各个 ...

  5. 在linux环境下编译运行OpenCV程序的两种方法

    原来以为在Ubuntu下安装好了OpenCV之后,自己写个简单的程序应该很容易吧,但是呢,就是为了编译一个简单的显示图片的程序我都快被弄崩溃了. 在谷歌和上StackOverFlow查看相关问题解答之 ...

  6. opencv 3.1.0 访问像素值的三种方法(C++)

    三种方法分别问: 指针访问:void colorReduce_ptr(cv::Mat &inputImage, cv::Mat &outputImage, int div); 迭代器访 ...

  7. 海康威视采集卡结合opencv使用(两种方法)-转

    (注:第一种方法是我的原创 ^_^. 第二种方法是从网上学习的.) 第一种方法:利用 板卡的API:  GetJpegImage 得到 Jpeg 格式的图像数据,然后用opencv里的一个函数进行解码 ...

  8. OpenCV坐标系与操作像素的四种方法

    像素是图像的基本组成单位,熟悉了如何操作像素,就能更好的理解对图像的各种处理变换的实现方式了. 1.at方法 第一种操作像素的方法是使用"at",如一幅3通道的彩色图像image的 ...

  9. OpenCV图像轮廓检测

    轮廓检测: 轮廓检测的原理通俗的说就是掏空内部点,比如原图中有3*3的矩形点.那么就可以将中间的那一点去掉. 一.关键函数1.1  cvFindContours函数功能:对图像进行轮廓检测,这个函数将 ...

  10. 学习opencv跟轮廓相关的

    查找轮廓 轮廓到底是什么?一个轮廓一般对应一系列的点,也就是图像中的一条曲线.表示的方法可能根据不同情况而有所不同.有多重方法可以表示曲线.在openCV中一般用序列来存储轮廓信息.序列中的每一个元素 ...

随机推荐

  1. cadence报错:Class must be one of IC, IO, DISCRETE, MECHANICAL, PLATING_BAR or DRIVER_CELL.

    在原理图文件上右键选择Edit Object Properties, 然后在class一栏中修改class为IC, IO, DISCRETE, MECHANICAL, PLATING_BAR or D ...

  2. Yii2安装步骤

    通过 Composer 安装了半天一直网络报错,配置了镜像,又报错依赖,运行跳过依赖,这个命令还是报错,我裂开. 最后只能利用归档文件安装,1.下http://www.yiiframework.com ...

  3. react native 上传图片(后面有空写一个,完整的案例)

    图片上传的思路很正确 https://www.jianshu.com/p/c9f030fa6754 1. 获取图片路径 利用react-native-image-crop-pick 从手机中获得图片的 ...

  4. Python 的入门学习之 Day4~6 ——from”夜曲编程“

    Day 4 time: 2021.8.1. 打卡第四天.今天起得很早(7点多一些),很棒,而梳头发更快些就更好了.我也算渐渐养成了晨间学习的习惯吧,一起床就心心念念着Python课程,这让我感觉到了生 ...

  5. iOS开发--APP性能检测方案汇总

    1 . CPU 占用率 CPU作为手机的中央处理器,可以说是手机最关键的组成部分,所有应用程序都需要它来调度运行,资源有限.所以当我们的APP因设计不当,使 CPU 持续以高负载运行,将会出现APP卡 ...

  6. Ubuntu22.04 KubeSphere 安装K8S集群

    Ubuntu22.04 KubeSphere 安装K8S集群_Ri0n的博客-CSDN博客 一.系统环境系统:Ubuntu 22.04集群IP分布hostname 角色 IP地址master mast ...

  7. react复制文案到剪切板

    这里使用别人写好的插件. 1.安装要用到的插件:copy-to-clipboard: 2.导入: import copy from 'copy-to-clipboard'; 3.使用: copy(co ...

  8. scala中变量常量字符串使用

    1.注释 scala注释使用与java完全一样: 2.变量和常量 (1).常量:在程序执行中,其值不会改变的变量: 基本语法:var 变量名称:变量类型 = 变量初始值 var num1:Int = ...

  9. 类继承(c++ primer plus)课后习题

    第一题: // base class class Cd { // represents a CD disk private: char performers[50]; char label[20]; ...

  10. nrm ls报错及npm镜像站点测速、切换

    报错截图: 解决方法: 1.win键,搜索powershell,点击"以管理员身份运行" 2.粘贴下面命令,回车,敲y,回车 set-ExecutionPolicy RemoteS ...