opencv之轮廓检测findContours

官方demo如下
python版:

ret, thresh = cv.threshold(imgray, 127, 255, 0)
contours, hierarchy = cv.findContours(thresh, cv.RETR_TREE, cv.CHAIN_APPROX_SIMPLE)

java版:

Mat cannyOutput = new Mat();
Imgproc.Canny(srcGray, cannyOutput, threshold, threshold * 2);
List<MatOfPoint> contours = new ArrayList<>();
Mat hierarchy = new Mat();
Imgproc.findContours(cannyOutput, contours, hierarchy, Imgproc.RETR_TREE, Imgproc.CHAIN_APPROX_SIMPLE);

C++版:

Mat canny_output;
Canny( src_gray, canny_output, thresh, thresh*2 );
vector<vector<Point> > contours;
vector<Vec4i> hierarchy;
findContours( canny_output, contours, hierarchy, RETR_TREE, CHAIN_APPROX_SIMPLE );
Mat drawing = Mat::zeros( canny_output.size(), CV_8UC3 );

参数

第一个参数是寻找轮廓的图像src;
第二个参数contours,是输出的轮廓,每一个轮廓用std::vector<std::vectorcv::Point >来存储;
第三个参数hierarchy,是输出的轮廓关系的存储;
第四个参数表示轮廓的检索模式,有四种(本文介绍的都是新的cv2接口):

    cv2.RETR_EXTERNAL     表示只检测外轮廓
    cv2.RETR_LIST  检测的轮廓不建立等级关系,但是轮廓之间都是单独的,没有父子关系;
    cv2.RETR_CCOMP     建立两个等级的轮廓,上面的一层为外边界,里面的一层为内孔的边界信息。如果内孔内还有一个连通物体,这个物体的边界也在顶层。
    cv2.RETR_TREE。 检测所有轮廓,所有轮廓按照真实的情况建立等级树结构关系,层数不限;

第五个参数method为轮廓的近似办法

cv2.CHAIN_APPROX_NONE 存储所有的轮廓点,相邻的两个点的像素位置差不超过1,即max(abs(x1-x2),abs(y2-y1))==1,算出来的轮廓不经过处理,算出来是啥就是啥;
cv2.CHAIN_APPROX_SIMPLE 压缩水平方向,垂直方向,对角线方向的元素,只保留该方向的终点坐标,(压缩轮廓,把横竖撇捺都压缩得只剩下顶点)例如一个矩形轮廓只需4个点来保存轮廓信息
cv2.CHAIN_APPROX_TC89_L1,CV_CHAIN_APPROX_TC89_KCOS 使用teh-Chinl chain 近似算法。

第六个参数offset:是输出轮廓的偏移量

返回值

返回两个值,一个是轮廓本身contours,还有一个是每条轮廓对应的属性hierarchy。

相关定义

在这里插入图片描述
1,轮廓点(border point):如果一个像素1在4-或者8-邻域找到一个像素为0的点,为一个轮廓点,如上图的B1,B2,B3,B4,其中阴影部分为1,白色部分为0
2,连通区域的环绕(surroundness among connected components),对于两个相邻的连通区域S1和S2,如果对于S1上任意一个点的4个方向,都能达到S2,那么S2b环绕S1
3,关于外轮廓(outer border)和孔轮廓(hole border),外轮廓是像素为1连通域内像素为0连通域环绕的轮廓点(如图一B4),孔轮廓是像素为0的连通区域被像素为1的连通区域环绕的轮廓点(如图一 B2)。
4,父轮廓(parent border),定义了层级关系,假设有像素为1的连通区域S1和像素为0的连通区域S2,并且S2环绕S1
(1)外轮廓S1的父轮廓为环绕S2的值为1的像素,如B3的父轮廓为B2
(2)如果S2是背景,父轮廓为frame 如B4父轮廓为frame
5,光栅扫描(RasterScan):是指从左往右,由上往下,先扫描完一行,再移至下一行起始位置继续扫描。
6,边界开始点(starting point):边界开始点分为外边界开始点(Fig.2a)和孔边界开始点(Fig.2b)。如果点(i,j)既满足(a)又满足(b),则把(i,j)视为外边界开始点。
7, NBD:从边界开始点(i,j)以边界跟踪算法可以得到一条边界,为每条新找到的边界B赋予一个新的唯一的编号,NBD表示当前跟踪的边界的编号。
8, LNBD:在光栅扫描的过程中,我们也保存最近遇到(上一个)的边界B’的编号,记为LNBD。

光栅扫描(RasterScan)

在这里插入图片描述
在这里插入图片描述

轮廓提取算法

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
参考
https://blog.csdn.net/hjxu2016/article/details/77833336
https://bbs.huaweicloud.com/blogs/detail/286678
https://docs.opencv.org/3.4/df/d0d/tutorial_find_contours.html
https://zhuanlan.zhihu.com/p/144807771
https://zhuanlan.zhihu.com/p/107257870

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值