Opencv笔记(十八)——轮廓的更多函数及其层次结构
凸缺陷
前面我们已经学习了轮廓的凸包,对象上的任何凹陷都被成为凸缺陷。OpenCV 中有一个函数 cv.convexityDefect() 可以帮助我们找到凸缺陷。函数调用如下:
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)
cv2.convexityDefects函数()会返回一个数组,其中每一行包含的值是 [起点,终点,最远的点,到最远点的近似距离]。我们可以在一张图上显示它。我们将起点和终点用一条绿线连接,在最远点画一个圆圈,要记住的是返回结果的前三个值是轮廓点的索引。所以我们还要到轮廓点中去找它们。
# coding=utf-8
import cv2
import numpy as np
img = cv2.imread("/home/wl/10.jpeg")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转灰度图
ret, thresh = cv2.threshold(img_gray, 175, 255, 0) #灰度图像二值化处理
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[1]
hull = cv2.convexHull(cnt,returnPoints = False) #找到凸包
defects = cv2.convexityDefects(cnt,hull) #找到凸包缺陷
print defects
print defects.shape
for i in range(defects.shape[0]):
s,e,f,d = defects[i,0]
start = tuple(cnt[s][0])
end = tuple(cnt[e][0])
far = tuple(cnt[f][0])
cv2.line(img,start,end,[0,255,0],2)
cv2.circle(img,far,5,[0,0,255],-1)
while(1):
cv2.imshow("img",img)
cv2.imwrite("/home/wl/baocun1.jpg", img)
k = cv2.waitKey(1) & 0XFF
if k==ord('q'):
break;
cv2.destroyAllWindows()
[[[ 358 0 365 15240]]
[[ 0 71 64 15164]]
[[ 71 166 107 14719]]
[[ 166 263 215 14848]]
[[ 263 358 322 14719]]]
(5, 1, 4)
点与多边形测试
求解图像中的一个点到一个对象轮廓的最短距离。如果点在轮廓的外部,返回值为负。如果在轮廓上,返回值为 0。如果在轮廓内部,返回值为正。下面我们以点(50,50)为例:
dist = cv2.pointPolygonTest(cnt,(50,50),True)
此函数的第三个参数是 measureDist。如果设置为 True,就会计算最短距离。如果是 False,只会判断这个点与轮廓之间的位置关系(返回值为+1,-1,0)。
# coding=utf-8
import cv2
import numpy as np
img = cv2.imread("/home/wl/10.jpeg")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转灰度图
ret, thresh = cv2.threshold(img_gray, 175, 255, 0) #灰度图像二值化处理
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt = contours[1]
dist = cv2.pointPolygonTest(cnt,(50,50),True)
dist1 = cv2.pointPolygonTest(cnt,(50,50),False)
print dist
print dist1
-178.997206682
-1.0
形状匹配
函数 cv2.matchShape() 可以帮我们比较两个形状或轮廓的相似度。如果返回值越小,匹配越好。它是根据 Hu 矩来计算的。
原图:
# coding=utf-8
import cv2
import numpy as np
img = cv2.imread("/home/wl/10.jpeg")
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY) #转灰度图
ret, thresh = cv2.threshold(img_gray, 175, 255, 0) #灰度图像二值化处理
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt0 = contours[0] #第一个轮廓
cnt1 = contours[1] #第二个轮廓
ret = cv2.matchShapes(cnt0,cnt1,1,0.0) #比较两个轮廓的相似度
ret1 = cv2.matchShapes(cnt0,cnt0,1,0.0) #跟自己比较
print ret
print ret1
0.215161556855
0.0
层次结构
什么是层次结构?
通常我们使用函数 cv2.findContours 在图片中查找一个对象。有时对象可能位于不同的位置。还有些情况,一个形状在另外一个形状的内部。这种情况下我们称外部的形状为父,内部的形状为子。按照这种方式分类,一幅图像中的所有轮廓之间就建立父子关系。这样我们就可以确定一个轮廓与其他轮廓是怎样连接的,比如它是不是某个轮廓的子轮廓,或者是父轮廓。这种关系就成为组织结构下图就是一个简单的例子:
在这幅图像中,我给这几个形状编号为 0-5。2 和 2a 分别代表最外边矩形的外轮廓和内轮廓。在这里边轮廓 0,1,2 在外部或最外边。我们可以称他们为(组织结构)0 级,简单来说就是他们属于同一级。接下来轮廓 2a。我们把它当成轮廓 2 的子轮廓。它就成为(组织结构)第
1 级。同样轮廓 3 是轮廓 2 的子轮廓,成为(组织结构)第 3 级。最后轮廓4,5 是轮廓 3a 的子轮廓,成为(组织结构)4 级(最后一级)。按照这种方式给这些形状编号,我们可以说轮廓 4 是轮廓 3a 的子轮廓(当然轮廓 5 也是)。
Opencv中的层次结构
每个轮廓都有它自己关于它是什么层级,谁是它的子类,谁是它的父类等等的信息。OpenCV将它表示为四个值的数组:[ 下一个(Next),前一个(Previous),第一个子类(First_Child),父类(Parent) ]
Next 表示同一级组织结构中的下一个轮廓。以上图中的轮廓 0 为例,轮廓 1 就是他的 Next。同样,轮廓 1 的 Next是 2,Next=2。那轮廓 2 呢?在同一级没有 Next。这时 Next=-1。
Previous 表示同一级结构中的前一个轮廓。与前面一样,轮廓 1 的 Previous 为轮廓 0,轮廓 2 的 Previous 为轮廓 1。轮廓 0 没有 Previous,所以 Previous=-1。
First_Child 表示它的第一个子轮廓。没有必要再解释了,轮廓 2 的子轮廓为 2a。所以它的 First_Child 为2a。那轮廓 3a 呢?它有两个子轮廓。但是我们只要第一个子轮廓,所以是轮廓 4。
Parent 表示它的父轮廓。与 First_Child 刚好相反。轮廓 4 和 5 的父轮廓是轮廓 3a。而轮廓 3a的父轮廓是 3。
注意:如果没有父或子,就为 -1。
轮廓检索模式
RETR_LIST
从解释的角度来看,这中应是最简单的。它只是提取所有的轮廓,而不去创建任何父子关系。换句话说就是“人人平等”,它们属于同一级组织轮廓。所以在这种情况下,组织结构数组的第三和第四个数都是 -1。但是,很明显,Next 和 Previous 要有对应的值。如果你不关心轮廓之间的关系,这是一个非常好的选择。
RETR_EXTERNAL
如果你选择这种模式的话,只会返回最外边的的轮廓,所有的子轮廓都会被忽略掉。所以在上图中使用这种模式的话只会返回最外边的轮廓(第 0 级):轮廓0,1,2。当你只想得到最外边的轮廓时,你可以选择这种模式。这在有些情况下很有用。
RETR_CCOMP
在这种模式下会返回所有的轮廓并将轮廓分为两级组织结构。
RETR_TREE
这种模式下会返回所有轮廓,并且创建一个完整的组织结构列表。它甚至会告诉你谁是爷爷,爸爸,儿子,孙子等。还是以上图为例,使用这种模式,对 OpenCV 返回的结果重新排序并分析它,红色数字是边界的序号,绿色是组织结构。
轮廓 0 的组织结构为 0,同一级中 Next 为 7,没有 Previous。子轮廓是 1,没有父轮廓。所以数组是 [7,-1,1,-1]。轮廓 1 的组织结构为 1,同一级中没有其他,没有 Previous。子轮廓是2,父轮廓为 0。所以数组是 [-1,-1,2,0]。
Opencv笔记(十八)——轮廓的更多函数及其层次结构的更多相关文章
- python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置
python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...
- (C/C++学习笔记) 十八. 继承和多态
十八. 继承和多态 ● 继承的概念 继承(inheritance): 以旧类为基础创建新类, 新类包含了旧类的数据成员和成员函数(除了构造函数和析构函数), 并且可以派生类中定义新成员. 形式: cl ...
- OpenCV学习笔记十八:opencv_flann模块
一,简介: Fast Library for Approximate Nearest Neighbors (FLANN)算法库.
- 嵌入式Linux驱动笔记(十八)------浅析V4L2框架之ioctl【转】
转自:https://blog.csdn.net/Guet_Kite/article/details/78574781 权声明:本文为 风筝 博主原创文章,未经博主允许不得转载!!!!!!谢谢合作 h ...
- Python学习第十八篇——低耦合函数设计思想
import json 2 def greet_user(filename): 3 try: 4 with open(filename) as f_obj: 5 username = json.loa ...
- 论文阅读笔记十八:ENet: A Deep Neural Network Architecture for Real-Time Semantic Segmentation(CVPR2016)
论文源址:https://arxiv.org/abs/1606.02147 tensorflow github: https://github.com/kwotsin/TensorFlow-ENet ...
- Opencv笔记(八)——图像上的算数运算
学习目标: 学习图像上的算术运算,加法,减法,位运算等. 学习函数cv2.add(),cv2.addWeighted() 等. 一.图像的加法 你可以使用函数 cv2.add() 将两幅图像进行加法运 ...
- JavaScript权威设计--事件冒泡,捕获,事件句柄,事件源,事件对象(简要学习笔记十八)
1.事件冒泡与事件捕获 2.事件与事件句柄 3.事件委托:利用事件的冒泡技术.子元素的事件最终会冒泡到父元素直到跟节点.事件监听会分析从子元素冒泡上来的事件. 事件委托的好处: 1.每个函 ...
- python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制
django Pagination(分页) django 自带的分页功能非常强大,我们来看一个简单的练习示例: #导入Paginator>>> from django.core.p ...
随机推荐
- 一本通1166 求f(x,n)
[题目描述] 已知 计算x=4.2,n=1以及x=2.5,n=15时f的值. [输入] 输入x和n. [输出] 函数值,保留两位小数. [输入样例] 4.2 10 [输出样例] 3.68 1.看见这种 ...
- Kmp--P3375 【模板】KMP字符串匹配
题目描述 如题,给出两个字符串 s1 和 s2,其中 s2 为 s1 的子串,求出 s2 在 s1 中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组 next. (如果你不知道这 ...
- 高级css效果
1.图片渐变效果 background linear-gradient(top,rgba(0,0,0,.8),rgba(0,0,0,.8))
- openstack trove mongodb配置项
systemLog.verbosity 组件的默认日志消息详细程度级别. 详细程度级别决定MongoDB输出的信息和调试消息量. 详细级别可以在0到5之间: 0是MongoDB的默认日志详细程度级别, ...
- 使用maven打包问题
项目打包:选择项目 右键->run as-> maven install . 项目中使用的是maven项目,将项目打包成war的时候有时候会出现 出现这种情况的时候解决步骤如下: 选择要打 ...
- 吴裕雄--天生自然MySQL学习笔记:MySQL 导入数据
1.mysql 命令导入 使用 mysql 命令导入语法格式为: mysql -u用户名 -p密码 < 要导入的数据库数据(runoob.sql) 实例: # mysql -uroot -p12 ...
- 元祖&字典
#什么是元祖:元祖是一个不可变的列表(没有改的需求) #======================================基本使用============================== ...
- Vue.js——4.指令 笔记
v-cloak:解决网速延迟 闪烁问题v-text=msg: 和{{}}表达式一样,没有闪烁问题,但是前后不能加别的,覆盖原本的内容 innerTextv-html=msg:innerHtml,一样可 ...
- App的布局管理
今天学习了布局管理器,格局自己的学习内容和课程,我主要学习了两种管理布局方式 一:LinearLayout线性布局 线性布局是指布局里面的内容成线性排列,有两种排列方式,横向排列和纵向排列,而排列方式 ...
- JZOJ-TG817-A-solution
T1 考虑是否有一种排序方法使得最优解都相邻,这种排序方法就是按照过一个点x的斜率为(P/Q)的直线的截距 排序之后考虑临项即可,O(N) T2 exit