接下来了解更多关于轮廓的函数。
前面我们学习了轮廓的凸包,对象上的人设凹陷都被称为凸缺陷。opencv里的convexityDefects()函数可以找到凸缺陷。
cv2.convexityDefects(contour, convexhull, convexityDefects=None)
第一个参数是轮廓,第二个参数是凸包上对应轮廓的点。函数会返回一个数组,每一行包含的值是【起点,终点,最远点,到最远点的近似距离】。下面的例子中起点终点用一根红线连接。
import cv2
import numpy as np
import matplotlib.pyplot as plt
img=cv2.imread('C:/Users/dell/Desktop/u12.jpg')
imgray=cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
ret,thresh=cv2.threshold(imgray,127,255,0)
image,coutours,hierarchy=cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cnt=coutours[1]
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,0,255],2)
cv2.circle(img,far,5,[255,0,0],-1)
cv2.imshow('img',img)
cv2.waitKey(0)
cv2.destroyAllWindows()
下面这个函数求得是点到轮廓的最短距离。cv2.poointPolygonTest()。
cv2.pointPolygonTest(contour, pt, measureDist)
第一个参数是轮廓;第二个参数是点的坐标;第三个参数如果设置为True,返回点与轮廓的最短距离,在内部的话就是负值,False的话只会判断点与轮廓的位置关系(0,-1,1)。
dist=cv2.pointPolygonTest(cnt,(50,50),False)
#输出结果:-1.0
我们利用cv2.matchShape()函数来帮助我们比较两个轮廓的相似度,返回的值越小匹配的结果越好。
cv2.matchShapes(contour1, contour2, method, parameter)
前两个参数是输入的两个轮廓或者是灰度图;第三个参数是method – Comparison method: CV_CONTOURS_MATCH_I1 , CV_CONTOURS_MATCH_I2 or CV_CONTOURS_MATCH_I3,有这三种形式;第四个参数没神魔用(官方文档说的。)
import cv2
import numpy as np
import matplotlib.pyplot as plt
img1=cv2.imread('C:/Users/dell/Desktop/00.jpg')
img2=cv2.imread('C:/Users/dell/Desktop/006.jpg')
plt.subplot(1,2,1),plt.imshow(img1)
plt.title('yurisa1'),plt.xticks([]),plt.yticks([])
plt.subplot(1,2,2),plt.imshow(img2)
plt.title('yurisa2'),plt.xticks([]),plt.yticks([])
plt.show()
gray1=cv2.cvtColor(img1,cv2.COLOR_BGR2GRAY)
gray2=cv2.cvtColor(img2,cv2.COLOR_BGR2GRAY)
rect=cv2.matchShapes(gray1,gray2,1,0)
print(rect)
#显示结果0.0010983665268929355
图象上传失败了,这里我在yurisa的博客找了两张图(注意图片的尺寸一定要一样),然后转化成灰度图,比较了她们的相似度,还是不错的。所以这个函数可以用在检验两张照片是否已同一个人上。
在前面的内容中我们使用的函数cv2.findContours来查找轮廓,我们总要设置一个参数:轮廓的提取模式(一般设置为cv2.RECT_LIST,cv2.RECT_TREE)。最后的这一届我们来探究他们的具体含义。
我们利用函数来查找一个对象,对象有事可能位于不同的位置。有些情况下,一个形状在另外一个形状的内部。这种情况下我们称为外部的形状为父,内部的形状为子,这样一幅图中所有的轮廓就建立了父子关系。
关于轮廓结构的数组每一行分别代表【next,Previous,first_child,Parent】
next代表同一级组织结构中的下一个轮廓,没有的话用-1表示。
previous代表同一级组织结构中的前一个轮廓,没有的话用-1拜师。
first_child代表他的第一个子轮廓(按照从上往下,从右往左的顺序)
parent代表父轮廓。
rect_list他提取所有的组织轮廓而不创造父子关系,他们共同属于同一级组织轮廓,所以数组的第三个和第三个数都是-1。
rect-external只会返回最外部的轮廓(第0级)。同样第三个和第四个数为-1。
rect_ccomp会返回所有的组织结构,并将轮廓分为两级组织结构(类似于二进制,二的下一级是一,一的下一级是二,无限循环)。
rect_tree最完美的一个,会返回所有轮廓并返回他们的关系父辈,子辈……