opencv threshold函数_新视界-OpenCV教程(21)- 轮廓:更多功能

aaaf17add6205e772689c4218ce08538.png

新视界-OpenCV教程系列文章

新视界-OpenCV教程(1)-入门介绍

OpenCV 中的图形用户界面特征系列

新视界-OpenCV教程(2)-图片入门

新视界-OpenCV教程(3)-视频入门

新视界-OpenCV教程(4)- 绘图功能

新视界-OpenCV教程(5)- 鼠标的画笔功能

新视界-OpenCV教程(6)- 作为调色板的轨迹栏

核心操作系列

新视界-OpenCV教程(7)- 对图片的基本操作

新视界-OpenCV教程(8)- 图像运算

新视界-OpenCV教程(9)- 性能测量和改进技术

OpenCV 中的图像处理系列

新视界-OpenCV教程(10)- 改变颜色空间

新视界-OpenCV教程(11)- 图像阈值

新视界-OpenCV教程(12)- 图像的几何变换

新视界-OpenCV教程(13)- 平滑图像

新视界-OpenCV教程(14)- 形态变换

新视界-OpenCV教程(15)- 图像梯度

新视界-OpenCV教程(16)- Canny 边缘检测

新视界-OpenCV教程(17)- 图像金字塔

新视界-OpenCV教程(18)- 轮廓:开端

新视界-OpenCV教程(19)- 轮廓:特征

新视界-OpenCV教程(20)- 轮廓:性质

本文目标

轮廓系列会分为5篇文章一一详细讲解。这是第四篇。

在本篇文章中,我们将学习凸性缺陷及其查找方法,如何求从一点到多边形的最短距离 和 如何匹配不同的形状。

091138da2987e650f7224b617177c30e.png

凸性缺陷

我们在先前文章中讨论过轮廓的凸包。该凸包中目标物体的任何偏差都可被视为凸性缺陷。

OpenCV 为我们提供了一个现成的函数,cv2.convexityDefects() 来解决这个问题。一个基本的函数调用如下所示:

hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)

记住,我们在寻找凸包时必须保证 returnPoints = False,才能顺利找到凸性缺陷。

我们上面的函数会返回一个数组作为结果,数组中每行包含这些:[起点、终点、最远点、到最远点的近似距离],这些我们可以用图像来表示:我们先画一条连接起点和终点的线,然后在最远处画一个圆。记住,返回的前三个值是cnt 的索引,所以我们必须从cnt 中得到这些值。代码如下:

import cv2
import numpy as np

# 导入图片,转换成灰度,得到阈值,轮廓,层级和cnt
img = cv2.imread('star.jpg')
img_gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret, thresh = cv2.threshold(img_gray, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt = contours[0]

# 使用凸性缺陷相关函数
hull = cv2.convexHull(cnt,returnPoints = False)
defects = cv2.convexityDefects(cnt,hull)

# 使用循环画出范围内的所有线和圆圈
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)

cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()

我们可以得到结果如下:

23f3b51ff9de45b97d4d6c26adcccf7c.png

点多边形测试

在这个部分中,我们的函数用来查找图像中某一点到轮廓线的最短距离。它返回的距离如果是负的,那么点在轮廓外;如果返回的值为正的,那么点在轮廓内;如果值为零,那么点在轮廓上。

例如,我们可以检查点(50,50),代码如下:

dist = cv2.pointPolygonTest(cnt,(50,50),True)

在上述函数中,第三个参数是measureDist。如果它为True,函数就会找到有符号的距离;如果为False,它就会查找该点是在等高线内还是外还是在等高线上(分别返回+1、-1、0)。

注意,如果目的不是求距离,我们则需要确保第三个参数是假的。因为,求距离是一个耗时的过程。如果让该参数为False,省去求距离的过程,我们会得到2-3 倍的加速。

匹配形状

OpenCV 还附带了一个函数cv2.matchShapes(),它使我们能够比较两个形状或两个轮廓,并返回一个显示相似性的度量。度量结果越低,匹配越好,它是根据hu 矩值计算的。

import cv2
import numpy as np

# 导入两张图
img1 = cv2.imread('star.jpg',0)
img2 = cv2.imread('star2.jpg',0)

# 得到阈值,轮廓,层级和两个cnt
ret, thresh = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
contours,hierarchy = cv2.findContours(thresh,2,1)
cnt1 = contours[0]
contours,hierarchy = cv2.findContours(thresh2,2,1)
cnt2 = contours[0]

# 利用匹配函数得到相似度
ret = cv2.matchShapes(cnt1,cnt2,1,0.0)
print ret

我尝试将特定的形状与下面给出的形状进行匹配:

091138da2987e650f7224b617177c30e.png

我得到了以下结果:

  • 将图像A与自身匹配,精度 = 0.0,完全相似
  • 图像A与图像B匹配,精度 = 0.001946,相似度非常高
  • 匹配图像A与图像C,精度 = 0.326911,相似度低

从上面的例子我们也可以看出,即使图像旋转对我们的比较也没有多大影响。

注:hu 矩是无论平移、旋转还是尺度变化都对其无影响的七个矩,第七项是偏不变量 skew-invariant,这些值我们可以使用cv2.HuMoments() 函数找到。


在下一篇文章中,将着重讲的是新视界-OpenCV教程(22)- 轮廓:层级。

如果你觉得我的文章有用,顺手点个赞,关注下我的专栏或则留下你的评论吧!

97c6718afec13eadfda7ff5341e7a212.png
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值