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 ...
随机推荐
- iOS下JS与原生的交互一
本篇主要讲的是UIWebView和JS的交互,在下一节会有wkWebView和JS交互的详解https://www.cnblogs.com/llhlj/p/9144110.html JS调用原生OC ...
- docker创建redis容器
1.拉取最新的redis镜像 docker pull redis; 2.创建存放redis数据的目录 mkdir /redis/data 3.查询redis镜像id docker images; RE ...
- 设置Apache(httpd)和Nginx 开机自启动
方法1: 进入目录: vi /etc/rc.d/rc.local #设置apache 和 nginx 开机自启动/usr/sbin/apachectl start/usr/sbin/nginx s ...
- 【php】Swoole之php高性能通信框架
Swoole介绍 swoole是由c语言开发的异步网络通信引擎,被编译为so文件(swoole.so)作为php的extesion扩展. 与其他普通扩展不同: 与普通的扩展不同的是普通的扩展只是提供一 ...
- jquery的读、写、增、删、查方法
# 注:jquery需要导包 格式<script type="text/javascript" src="jquery-3.2.1.js">> ...
- 手机与Arduino蓝牙串口通讯实验及完整例程
安卓手机与Arduino之间采用蓝牙串口通讯,是很多智能装置和互动装置常用的控制方法,简单而有效,无需网络环境,很实用的技术. 实验采用Arduino UNO板,加了一块1602LCD屏做显示(因为只 ...
- django_filter的values / values_list
from django.db import models class Blog(models.Model): name = models.CharField(max_length=100) tagli ...
- 视频课程 | Kubernetes的兴起
视频课程 | Kubernetes的兴起 原创: 京小云 京东云开发者社区 4月3日 京东云开发者社区在3月底于北京举行了以"Cloud Native时代的应用之路与开源创新"为 ...
- IO读写
1.read & write read: 把数据从内核缓冲区复制到进程缓冲区. write: 把数据从进程缓冲区复制到内核缓冲区. 上层程序的IO操作.不是物理设备级别的读写,而是缓存的复制. ...
- 2020/1/28 PHP代码审计之命令执行漏洞
0x00 命令执行漏洞原理 应用程序有时需要调用一些执行系统命令的函数,如在PHP中,使用system.exec.shell_exec.passthru.popen.proc_popen等函数可以执行 ...