如何在OpenCV Python中匹配图像形状?
我们使用 cv2.matchShapes() 函数来匹配两个图像形状。该函数返回一个度量标准,显示图像形状之间的相似性。该函数使用Hu矩来计算度量值。度量值越低,图像形状之间的相似性就越高。
在以下示例中,我们将匹配来自不同图像的形状以及单个图像中的形状。
语法
我们使用以下语法来匹配两个图像形状-
ret = cv2.matchShapes(cnt1,cnt1,1,0.0)
其中,
- cnt1 - 第一个图像形状的轮廓点
-
cnt2 - 第二个图像形状的轮廓点
步骤
您可以使用以下步骤来匹配两个图像形状-
导入所需的库。在所有以下Python示例中,所需的Python库都是 OpenCV 。请确保您已经安装了它。
import cv2
使用 cv2.imread() 将输入图像作为灰度图像读取。
img1 = cv2.imread('star.png',0)
img2 = cv2.imread('star1.png',0)
在灰度图像上应用阈值处理,以创建二进制图像。
ret,thresh1 = cv2.threshold(img1,150,255,0 )
ret,thresh2 = cv2.threshold(img1,150,255,0 )
在二进制图像中查找形状的轮廓,使用 cv2.findContours() 函数。
contours1,_ = cv2.findContours(thresh1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
contours2,_ = cv2.findContours(thresh2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
从每个图像中选择特定的轮廓,并应用形状匹配函数 cv2.matchShapes() 传递所选择的轮廓。
cnt1 = contours1 [0]
cnt2 = contours2 [0]
ret12 = cv2.matchShapes(cnt1,cnt2,1,0.0)
打印结果值,即图像形状匹配度量。值越低,匹配越好。
print("与图像1匹配的图像2:",ret12)
让我们看一些例子,以便更好地理解。
示例1
在此程序中,我们匹配两个图像形状。每个图像都包含一个单一形状。我们还将从每个图像中匹配形状与自身的形状。
# 导入所需库
import cv2
# 读取两幅灰度图像
img1 = cv2.imread('star.png',0)
img2 = cv2.imread('pentagon.png',0)
# 对图像应用阈值处理以转换为二进制图像
ret, thresh1 = cv2.threshold(img1, 127, 255,0)
ret, thresh2 = cv2.threshold(img2, 127, 255,0)
# 在二进制图像中找出轮廓
contours1, hierarchy = cv2.findContours(thresh1,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print("在第一张图像中检测到的形状数量:",len(contours))
cnt1 = contours1[0]
contours2, hierarchy = cv2.findContours(thresh2,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print("在第二张图像中检测到的形状数量:",len(contours))
cnt2 = contours2[0]
# 计算匹配分数
ret11 = cv2.matchShapes(cnt1,cnt1,1,0.0)
ret22 = cv2.matchShapes(cnt2,cnt2,1,0.0)
ret12 = cv2.matchShapes(cnt1,cnt2,1,0.0)
# 输出匹配分数
print("将第一张图像与自身匹配:", ret11)
print("将第二张图像与自身匹配:", ret22)
print("将第一张图像与第二张图像匹配:", ret12)
将下面的图像视为上述程序中提到的输入图像 ‘ star.png ‘ 和 ‘ pentagon.png ‘。
输出
执行后,上述代码将产生以下输出:
在第一张图像中检测到的形状数量: 1
在第二张图像中检测到的形状数量: 1
将第一张图像与自身匹配: 0.0
将第二张图像与自身匹配: 0.0
将第一张图像与第二张图像匹配: 0.6015851094057714
示例 2
在本程序中,我们匹配图像中的形状。我们检测图像中的三个形状。
import cv2
import numpy as np
img = cv2.imread('convexhull.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
ret,thresh = cv2.threshold(gray,100,255,0)
contours,hierarchy = cv2.findContours(thresh, cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
print("发现的形状数量:",len(contours))
# draw contour and shape number
for i, cnt in enumerate(contours):
M = cv2.moments(cnt)
x1, y1 = cnt[0,0]
img1 = cv2.drawContours(img, [cnt], -1, (0,255,255), 3)
cv2.putText(img1, f'形状:{i+1}', (x1, y1), cv2.FONT_HERSHEY_SIMPLEX, 0.6, (0, 255, 0), 2)
cnt1 = contours[0]
cnt2 = contours[1]
cnt3= contours[2]
ret11 = cv2.matchShapes(cnt1,cnt1,1,0.0)
ret12 = cv2.matchShapes(cnt1,cnt2,1,0.0)
ret23 = cv2.matchShapes(cnt2,cnt3,1,0.0)
ret31 = cv2.matchShapes(cnt3,cnt1,1,0.0)
print("第一种形状与自身的匹配度:", ret11)
print("第一种形状与第二种形状的匹配度:", ret12)
print("第二种形状与第三种形状的匹配度:", ret23)
print("第三种形状与第一种形状的匹配度:", ret31)
cv2.imshow("形状", img)
cv2.waitKey(0)
cv2.destroyAllWindows()
在这个程序中,我们将使用下面的图像和 输入文件 −
输出
执行上述代码后,将产生以下输出−
探测到的形状数量:3
将形状1与其自身匹配:0.0
将形状1与形状2匹配:0.15261042892128207
将形状2与形状3匹配:0.9192709496955178
将形状3与形状1匹配:0.7521097407160106
我们得到以下窗口,显示输出结果 −
基于上述结果,我们得出形状1与形状2更相似,而不是形状3。