如何在OpenCV Python中匹配图像形状?
OpenCV是一个流行的计算机视觉库,它提供了许多有用的图像处理功能。其中之一便是匹配图像形状。在这篇文章里,我将会教你如何使用OpenCV Python进行图像形状匹配。
准备工作
在开始之前,我们需要准备以下工作:
- 安装Python和OpenCV
- 下载示例图像
为了方便演示,我们将会使用一张简单的图像。你可以访问以下链接并下载示例图像:https://d1ex6o2ulrvyue.cloudfront.net/wp-content/uploads/2019/06/shapes.png
导入必要的库和图像
下载示例图像之后,让我们来看一下Python代码。首先,我们需要导入必要的库:
import cv2
import numpy as np
from matplotlib import pyplot as plt
我们还需要将图像加载到Python中:
# 读取示例图像
img = cv2.imread('shapes.png')
然后我们可以显示图片:
# 显示示例图像
plt.imshow(img)
plt.title('Example Image')
plt.show()
这幅图像包含了三种不同形状:圆、三角形和矩形。我们将使用这幅图像来测试我们的形状匹配算法。
形状匹配算法
有很多不同的图像形状匹配算法,例如Hu矩、Zernike矩和小波矩。在这篇文章里,我们将使用轮廓匹配算法来匹配图像的形状。
轮廓(Contour)
轮廓是图像中所有连续的点(边界)的曲线。在OpenCV Python中,我们可以使用findContours函数来查找轮廓。
# 找到所有轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
这里的thresh是先前预处理过的图像,我们使用的是cv2.CHAIN_APPROX_SIMPLE近似方法来查找轮廓。理解轮廓最好的方法之一,就是将其可视化。以下代码可以绘制轮廓以及原始图像:
# 绘制轮廓
contour_image = cv2.drawContours(img.copy(), contours, -1, (0,255,0), 3)
# 显示图像
plt.imshow(contour_image)
plt.title('Contour Image')
plt.show()
该图像是原始图像的复制,并显示了找到的轮廓。现在,我们已经找到了图像中所有的轮廓,接下来我们需要确定每个轮廓的形状。
形状确定
在确定轮廓的形状之前,我们需要先了解如何计算轮廓特征。计算轮廓特征最常用的方法之一是Hu矩。在OpenCV Python中,我们可以使用moments函数来计算Hu矩。以下是示例代码:
# 计算轮廓特征
shape_features = np.zeros([len(contours), 7])
for i, c in enumerate(contours):
# Hu矩
moments = cv2.moments(c)
hu_moments = cv2.HuMoments(moments)
shape_features[i]= np.log(np.abs(hu_moments))
在这段代码中,我们首先创建了一个数组来存储每个轮廓的特征。然后我们遍历所有的轮廓,并计算每个轮廓的Hu矩,将其存储在shape_features数组中。
现在我们已经计算了所有形状的特征,接下来我们需要使用这些特征来确定每个轮廓的形状。以下是示例代码:
# 确定轮廓形状
shapes = []
for feature in shape_features:
# 圆形
if feature[0] < -1.0 and feature[2] < -1.0:
shapes.append('Circle')
# 三角形
elif feature[1] < -1.0:
shapes.append('Triangle')
# 矩形
else:
shapes.append('Rectangle')
在这段代码中,我们使用了如下规则:
- 如果第一项Hu矩和第三项Hu矩都小于-1,我们认为这是一个圆形。
- 如果第二项Hu矩小于-1,我们认为这是一个三角形。
- 如果不满足以上两个条件,我们认为这是矩形。
完整代码
import cv2
import numpy as np
from matplotlib import pyplot as plt
# 读取示例图像
img = cv2.imread('shapes.png')
# 灰度化处理
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化处理
_, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
# 找到所有轮廓
contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓
contour_image = cv2.drawContours(img.copy(), contours, -1, (0,255,0), 3)
# 显示图像
plt.imshow(contour_image)
plt.title('Contour Image')
plt.show()
# 计算轮廓特征
shape_features = np.zeros([len(contours), 7])
for i, c in enumerate(contours):
# Hu矩
moments = cv2.moments(c)
hu_moments = cv2.HuMoments(moments)
shape_features[i] = np.log(np.abs(hu_moments))
# 确定轮廓形状
shapes = []
for feature in shape_features:
# 圆形
if feature[0] < -1.0 and feature[2] < -1.0:
shapes.append('Circle')
# 三角形
elif feature[1] < -1.0:
shapes.append('Triangle')
# 矩形
else:
shapes.append('Rectangle')
# 打印形状
print(shapes)
结论
在这篇文章中,我们使用OpenCV Python匹配了图像的形状。我们介绍了轮廓、Hu矩和轮廓匹配算法,并演示了如何在Python中实现这些功能。我希望这篇文章能帮助你更好地理解OpenCV Python中的形状匹配功能。