【一文读懂】Contours Hierarchy ——opencv边界的继承结构,表格的提取,表格孔洞处理,空心形状结构的提取
【参考】opencv文档
Contours Hierarchy
关于边界的继承结构,例如边界的父子结构
使用 cv2.findContours(),我们需要选择边界回溯模式,例如:cv2.RETR_LIST
或者 cv2.RETR_TREE
函数得到的三个数组,第一个是图片,第二个是边界,第三个是继承结构 hierarchy,一般我们都只用后面两个。
形式如:
python:
contours, hierarchy = cv2.findContours(img, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
有时一些图片对象在不同的位置上,但有时候,一些图形会在另一些图形之中,被包含在内部。
例如:黑色区域就被包含在白色区域中,而白色区域外面又有黑色区域,这样就把外层称为是 父层(红色),内层称为是孩子层(绿色)。
这样一来,我们就可以找出不同的形状间的关系了,例如我们可以分辨出一个边界是如何和其他边界联系的了,例如它是否是一些边界的父边界,或者是另一些边界的孩子边界,这就叫做hierarchy
例如:
说明:
在这张图片里,0,1,2边界是最外层的边界,称为0层(绿色),或者简单地说,他们在同一层次上(没有互相之间的包含关系)
下一层是2a,它是层2的子层,注意是白框内部的部分!我们这里说的一直是边界!!所以它是层1(粉色)。
类似的,边界3是2a的子层,是层2(蓝色),
3a是3的子层,是层3(红色)
最后是4,5层,他们是3a层的子层,是最后一层,是层4(黄色)
所以每个边界都有关于它是哪一个层次的信息,记录结构为:[Next, Previous, First_Child, Parent]
[下一个,上一个,第一个孩子层,父层(上一层)]
参考java版本:Java OpenCV findContours函数RETR_CCOMP轮廓顺序
ds[0]->同层级的下一个轮廓(不存在为-1)
ds[1]->同层级的上一个轮廓(不存在为-1)
ds[2]->第一个子轮廓(不存在为-1)
ds[3]->父轮廓(不存在为-1)
例如:
对于边界0,它的下一个同级边界是边界1,上一个同级轮廓没有,第一个子轮廓没有,没有父轮廓,所以是
[1,-1,-1,-1]
边界2的上一个同级边界是边界1,下一个同级边界没有,第一个子轮廓是2a,没有父轮廓,所以是
[-1,1,2a,-1]
不同的边界flag表示不一样的意思:
cv2.RETR_LIST, cv2.RETR_TREE, cv2.RETR_CCOMP, cv2.RETR_EXTERNAL
1. RETR_LIST
父子结构都不管了,他们只是单纯的边界结构,他们都属于同一层。所以得到的结果是:
>>> hierarchy2 array([[[ 1, -1, -1, -1],3 [ 2, 0, -1, -1],4 [ 3, 1, -1, -1],5 [ 4, 2, -1, -1],6 [ 5, 3, -1, -1],7 [ 6, 4, -1, -1],8 [ 7, 5, -1, -1],9 [-1, 6, -1, -1]]])
2. RETR_EXTERNAL
这个模式只返回外层边界,所有的子层都不要了
在这个规则下,只考虑“最老的人”,其他人全都不考虑。
1 >>> hierarchy2 array([[[ 1, -1, -1, -1],3 [ 2, 0, -1, -1],4 [-1, 1, -1, -1]]])
当你只要外层边界的时候,这个标志位很有用。
3. RETR_CCOMP
这个标志会返回全部的边界,但是会把它们分为两层,可以算是一种简化吧,例如:
用两种颜色标志就是下面这样的:一层绿色一层粉色
所以可以看到只有两层结构,要么是外层要么是里层,
1 >>> hierarchy2 array([[[ 3, -1, 1, -1],3 [ 2, -1, -1, 0],4 [-1, 1, -1, 0],5 [ 5, 0, 4, -1],6 [-1, -1, -1, 3],7 [ 7, 3, 6, -1],8 [-1, -1, -1, 5],9 [ 8, 5, -1, -1],10 [-1, 7, -1, -1]]])
注意:
ds[0]->同层级的下一个轮廓(不存在为-1)
ds[1]->同层级的上一个轮廓(不存在为-1)
ds[2]->第一个子轮廓(不存在为-1)
ds[3]->父轮廓(不存在为-1)
这里为什么父层不是为0或者-1呢?
因为每层标志都必须用真实标志,所以层也要按照父子关系来,需要用每一层的真实标号。
如果只想显示父层或者子层,可以通过层与层记录之间的关系来达到,隔一层记录一次,或者仅仅遍历某层之间的上一个和下一个。
例如,
从hierachy[0][0][0]
开始,有上一个轮廓不存在,下一个轮廓是3,
所以查询轮廓hierachy[0][0][3]
,可见[ 5, 0, 4, -1]
,同级别的下一个轮廓是5,查询hierachy[0][0][5]
,下一个轮廓是hierachy[0][0][7] [ 8, 5, -1, -1],
,下一个轮廓是hierachy[0][0][8], [-1, 7, -1, -1]
,下一个轮廓是-1不存在,得到了0,3,5,7,8,都是一层,和图片相符,而且有子轮廓,是外层(父层)
同理,1,2,4,6是一层,都是子层(内层)
代码实现:
OpenCV中findContours轮廓提取一个边缘只对应的一个轮廓
opencv轮廓提取的时候,图像中一条边缘有查找到两个轮廓。当然只提取最外轮廓是不会出现重复情况,但设置提取所有轮廓会出现两个轮廓,对于利用得到的轮廓进一步处理带来不必要的麻烦,所以需要从一条轮廓开始,然后找他的同级链,直到找到结尾。
这样的处理方式就不会有双层轮廓的问题了。
由于截图有些噪点,边框白色部分又比较小,显示出来的效果一般。
当我把图片反转为~img
时,用于检测表格:
表格检测代码:
import cv2if __name__ =='__main__':image = cv2.imread('mask1.jpg')img = cv2.cvtColor(image,cv2.COLOR_BGR2GRAY)img = cv2.adaptiveThreshold(~img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2) contours,hierachy = cv2.findContours(img, cv2.RETR_CCOMP,cv2.CHAIN_APPROX_SIMPLE)# 查找内层的例子:i=0hierach_id = 0inner_class =[]# 一直搜索到找到没有子轮廓的结构,且注意搜索长度不能超过边界数目while(hierachy[0][i][2]!=-1 and hierachy[0][i][1]==-1 and i<len(contours) and hierachy[0][i][3]!=-1):hierach_id = ii+=1print(hierach_id,hierachy[0][hierach_id])while(hierachy[0][hierach_id][0]!=-1):inner_class.append(contours[hierach_id])hierach_id=hierachy[0][hierach_id][0]print(hierach_id,hierachy[0][hierach_id])for cnt in inner_class: # 画图cv2.drawContours(image,[cnt],0,(122,122,0),3)cv2.imshow('img',image)cv2.waitKey(10000)
把
img = cv2.adaptiveThreshold(~img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2)
改为:
img = cv2.adaptiveThreshold(img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, 15, -2)
也就是图片黑白反转回来就是检测外侧边框了:
最后一个4. RETR_TREE
It even tells, who is the grandpa, father, son, grandson and even beyond…
【一文读懂】Contours Hierarchy ——opencv边界的继承结构,表格的提取,表格孔洞处理,空心形状结构的提取相关推荐
- 一文读懂 HTTPS 与 TLS证书链校验
一文读懂 HTTPS 与 TLS证书链校验 前一段时间在看X.509证书结构 与 TLS证书校验链相关知识,到今天感觉基本了解清楚,想着写一篇文章记录学习心得. 在实际工作中,涉及到X.509证书结构 ...
- 一文读懂Faster RCNN
来源:信息网络工程研究中心本文约7500字,建议阅读10+分钟 本文从四个切入点为你介绍Faster R-CNN网络. 经过R-CNN和Fast RCNN的积淀,Ross B. Girshick在20 ...
- 一文读懂EfficientDet
一文读懂EfficientDet. 今年年初Google Brain团队在 CVPR 2020 上发布了 EfficientDet目标检测模型, EfficientDet是一系列可扩展的高效的目标检测 ...
- 从根上理解高性能、高并发(七):深入操作系统,一文读懂进程、线程、协程
本文引用了"一文读懂什么是进程.线程.协程"一文的主要内容,感谢原作者的无私分享. 1.系列文章引言 1.1 文章目的 作为即时通讯技术的开发者来说,高性能.高并发相关的技术概念早 ...
- 一文读懂什么是EPP、EDR、CWPP、HIDS及业内主流产品
一文读懂什么是EPP.EDR.CWPP.HIDS及业内主流产品 当前终端安全概念包括:针对云工作负载保护平台cwpp.端点防护平台epp和终端全检测响应平台edr.HIDS品类(长亭牧云.青藤万相)更 ...
- python随机森林变量重要性_推荐 :一文读懂随机森林的解释和实现(附python代码)...
原标题:推荐 :一文读懂随机森林的解释和实现(附python代码) 作者:WilliamKoehrsen:翻译:和中华:校对:李润嘉 本文约6000字,建议阅读15分钟. 本文从单棵决策树讲起,然后逐 ...
- 一文读懂高速互联的阻抗及反射(中)
一文读懂高速互联的阻抗及反射(中) 勘误: 上篇中:电感的电抗叫做感抗,表示为: X L = j ω C X_L = {j \omega C} XL=jωC 上述公式应该改为: X L = j ω ...
- 空间计量 python_一文读懂空间计量入门之空间数据、权重矩阵、空间统计、空间模型等简介...
原标题:一文读懂空间计量入门之空间数据.权重矩阵.空间统计.空间模型等简介 来源:计量经济学服务中心编辑整理,转载请联系 1 前言 空间分析起源于地理学.空间经济学和相关学科.到目前为止,它被认为是专 ...
- 一文读懂 YOLOv1,v2,v3,v4 发展史
YOLO 系列算法是目标检测 one-stage 类的代表算法,本文将从 问题背景,创新点等方面比较,了解它们的的发展历程. two-stage 相关: 一文读懂 R-CNN,Fast R-CNN,F ...
- 一文读懂SCADA、DCS与PLC之间的不同
一文读懂SCADA.DCS与PLC之间的不同 - 知乎 一文读懂SCADA.DCS与PLC之间的不同 - 知乎随着工业企业智能化应用水平的提升,越来越多的人开始接触到各种工业自动化系统和产品,比较常见 ...
最新文章
- 太厉害了!目前 Redis 可视化工具最全的横向评测
- 慧鱼机器人编程语言的特点_慧鱼机器人课程设计报告.doc
- 按频率对元素进行排序
- win10如何查看文件夹的大小 - 方法大全
- 漫步数学分析七——集合的闭包
- 一周最新示例代码回顾 (4/2–4/8)
- centos7使用kubeadm部署k8s集群(使用containerd做运行时)
- 一文告诉你Java素数怎么判断
- 爬虫 | 破解APP中阿里云滑动验证码
- u盘扩容盘用什么软件测试,如何检测所购买的U盘是否为扩容盘?
- 微信获取粉丝信息php,1.2 微信粉丝用户及粉丝标签管理
- PR:设置关键帧、调出效果搜索栏找到裁剪效果
- 基于机器学习进行销售预测分析
- 安徽大学计算机复试刷人比例,658人进复试刷掉564多人!盘点21复试比奇高、刷人狠的院校专业...
- Android 上唯一好用的图片标注 App:马克标注
- k8s关于Orphaned pod <pod_id> found,volume paths are still present on disk 的解决方法
- JAVA面试题集(2) (转)
- Machine Learning - Coursera 吴恩达机器学习教程 Week1 学习笔记
- SAP 的总账和明细账
- stata里reghdfe函数在不同固定效应设计下的观测值问题