凸缺陷

前面我们已经学习了轮廓的凸包,对象上的任何凹陷都被成为凸缺陷。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笔记(十八)——轮廓的更多函数及其层次结构的更多相关文章

  1. python3.4学习笔记(十八) pycharm 安装使用、注册码、显示行号和字体大小等常用设置

    python3.4学习笔记(十八) pycharm 安装使用.注册码.显示行号和字体大小等常用设置Download JetBrains Python IDE :: PyCharmhttp://www. ...

  2. (C/C++学习笔记) 十八. 继承和多态

    十八. 继承和多态 ● 继承的概念 继承(inheritance): 以旧类为基础创建新类, 新类包含了旧类的数据成员和成员函数(除了构造函数和析构函数), 并且可以派生类中定义新成员. 形式: cl ...

  3. OpenCV学习笔记十八:opencv_flann模块

    一,简介: Fast Library for Approximate Nearest Neighbors (FLANN)算法库.

  4. 嵌入式Linux驱动笔记(十八)------浅析V4L2框架之ioctl【转】

    转自:https://blog.csdn.net/Guet_Kite/article/details/78574781 权声明:本文为 风筝 博主原创文章,未经博主允许不得转载!!!!!!谢谢合作 h ...

  5. Python学习第十八篇——低耦合函数设计思想

    import json 2 def greet_user(filename): 3 try: 4 with open(filename) as f_obj: 5 username = json.loa ...

  6. 论文阅读笔记十八: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 ...

  7. Opencv笔记(八)——图像上的算数运算

    学习目标: 学习图像上的算术运算,加法,减法,位运算等. 学习函数cv2.add(),cv2.addWeighted() 等. 一.图像的加法 你可以使用函数 cv2.add() 将两幅图像进行加法运 ...

  8. JavaScript权威设计--事件冒泡,捕获,事件句柄,事件源,事件对象(简要学习笔记十八)

    1.事件冒泡与事件捕获 2.事件与事件句柄   3.事件委托:利用事件的冒泡技术.子元素的事件最终会冒泡到父元素直到跟节点.事件监听会分析从子元素冒泡上来的事件. 事件委托的好处:     1.每个函 ...

  9. python 学习笔记十八 django深入学习三 分页,自定义标签,权限机制

    django  Pagination(分页) django 自带的分页功能非常强大,我们来看一个简单的练习示例: #导入Paginator>>> from django.core.p ...

随机推荐

  1. 【STM32H7教程】第48章 STM32H7的FMC总线应用之是32路高速IO扩展

    完整教程下载地址:http://www.armbbs.cn/forum.php?mod=viewthread&tid=86980 第48章       STM32H7的FMC总线应用之是32路 ...

  2. Transaction Managament(事务管理二、Spring事务)

    Transaction Managament(事务管理二.Spring事务) Spring事务框架的优势 ​ Spring事务框架将开放过程中事务管理相关的关注点进行了分离,对这些关注点进行了抽象分离 ...

  3. Assignment写作需要掌握的两种表达方式

    在正式开始写Assignment之前都会进行文献检索和整理,选择适合Assignment选题的文献资料进行阅读和引用.对于文献中与自己的观点高度相关的参考资料要如何具体引用,而不造成抄袭或者增加文章的 ...

  4. 基本pipline用法

    #!groovynode { stage('代码获取') { checkout([$class: 'SubversionSCM', additionalCredentials: [], exclude ...

  5. StarUML类图相关——关联、聚合、组合、泛化、依赖、实现

    在阅读设计模式相关的书籍,或者其他一些项目.相关博客等等,经常会遇到类图,它对于一个类的信息,如变量.方法及其可见性,类与类(接口)之间的继承关系.依赖关系.聚合关系.组合关系等,都可以比较形象得当地 ...

  6. BZOJ [Cqoi2017] 小Q的棋盘

    题解:枚举最后在哪里停止,然后剩下的步数/2 也就是找最大深度 枚举终止位置算是一种思路吧 #include<iostream> #include<cstdio> #inclu ...

  7. 第一个eclipse maven项目!我超全!

    前言:以前一直用idea做东西,今天突然想试一下,没想到配置起来是真的麻烦!!!!会出现各种各样的问题,太晚了,本文只做出几处非常严重的问题,如有疑问,请私信,留言 准备:本文     JDK 1.8 ...

  8. SPOJ 423 Assignments 状态DP

    这个题目搁置了这么久,终于搞完了. 给n个人分配n个课程,已经告诉了你n个人对哪几门感兴趣,问最多有多少种分配方式 我刚开始都没找到这怎么还可以状态dp,哪来的状态转移,想用暴力DFS,果断TLE的妥 ...

  9. 哈希表hashTable的Java设计

    1:哈希表的概念 2:设计原理 3:哈希表的Java设计

  10. 干货 | 快速实现数据导入及简单DCS的实现

    干货 | 快速实现数据导入及简单DCS的实现 原创: 赵琦 京东云开发者社区  4月18日 对于多数用户而言,在利用云计算的大数据服务时首先要面临的一个问题就是如何将已有存量数据快捷的导入到大数据仓库 ...