目录
图像形状检测是计算机视觉领域中的一项关键技术,广泛应用于工业自动化、机器人视觉、医学图像处理等多个领域。本文将详细介绍如何使用Python和OpenCV库实现图像形状检测,通过简洁明了的步骤和代码示例,帮助你快速掌握这一技能。
一、环境准备
在开始之前,确保你的电脑上已经安装了Python和OpenCV库。你可以通过以下命令来安装OpenCV库:
pip install opencv-python
同时,确保你能够编写和运行Python代码,并熟悉基本的图像处理概念。
二、读取和预处理图像
读取图像
使用OpenCV的cv2.imread()函数读取图像文件。例如,读取一张包含不同形状的图像:
python
import cv2
# 读取图像
img = cv2.imread('shapes.png')
灰度化
将彩色图像转换为灰度图像,以简化后续处理。使用cv2.cvtColor()函数:
python
# 转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
滤波去噪
使用高斯模糊来去除图像中的噪声。高斯模糊是一种常用的图像处理技术,可以平滑图像并减少噪声干扰。使用cv2.GaussianBlur()函数:
python
# 高斯模糊
blurred_img = cv2.GaussianBlur(gray_img, (5, 5), 0)
三、边缘检测
边缘检测是形状检测的重要步骤,它可以帮助我们找到图像中的轮廓。使用Canny边缘检测算法,该算法是一种常用的边缘检测算法,具有良好的边缘检测效果。使用cv2.Canny()函数:
python
# Canny边缘检测
edges = cv2.Canny(blurred_img, 50, 150)
四、查找轮廓
使用cv2.findContours()函数查找图像中的轮廓。该函数会返回轮廓点集、层次结构和轮廓的近似方法。我们主要关注轮廓点集:
python
# 查找轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
五、绘制轮廓
为了可视化检测到的轮廓,我们可以使用cv2.drawContours()函数在原图像上绘制轮廓:
python
# 绘制轮廓
contour_img = img.copy()
cv2.drawContours(contour_img, contours, -1, (0, 255, 0), 2)
六、形状分类
根据轮廓的顶点数目、面积、周长等特征,我们可以对检测到的形状进行分类。以下是一个简单的形状分类示例:
python
for contour in contours:
# 计算轮廓面积
area = cv2.contourArea(contour)
# 计算轮廓周长
perimeter = cv2.arcLength(contour, True)
# 近似轮廓为多边形
epsilon = 0.02 * perimeter
approx = cv2.approxPolyDP(contour, epsilon, True)
# 获取轮廓顶点数目
num_vertices = len(approx)
# 根据顶点数目判断形状
shape = 'Unknown'
if num_vertices == 3:
shape = 'Triangle'
elif num_vertices == 4:
# 判断是否为正方形或矩形
x, y, w, h = cv2.boundingRect(approx)
aspect_ratio = w / float(h)
if 0.95 < aspect_ratio < 1.05:
shape = 'Square'
else:
shape = 'Rectangle'
elif num_vertices == 5:
shape = 'Pentagon'
elif num_vertices == 6:
shape = 'Hexagon'
else:
# 对于顶点数目大于6的形状,可以根据周长面积比等特征进一步分类
# 例如,圆形可以通过周长面积比接近某个阈值来判断
if 4 * 3.14 * (area / 3.14) ** 0.5 / perimeter > 0.8 and 4 * 3.14 * (area / 3.14) ** 0.5 / perimeter < 1.2:
shape = 'Circle'
else:
shape = 'Other Polygon'
# 在图像上标注形状名称和顶点数目
M = cv2.moments(contour)
if M['m00'] != 0:
cX = int(M['m10'] / M['m00'])
cY = int(M['m01'] / M['m00'])
else:
cX, cY = 0, 0
cv2.putText(contour_img, f'{shape} ({num_vertices} vertices)', (cX - 50, cY - 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
cv2.drawContours(contour_img, [approx], -1, (0, 0, 255), 2)
七、显示结果
最后,使用cv2.imshow()函数显示处理后的图像:
python
# 显示结果图像
cv2.imshow('Shape Detection', contour_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
八、完整代码示例
以下是完整的代码示例,将上述步骤整合在一起:
python
import cv2
# 读取图像
img = cv2.imread('shapes.png')
# 转换为灰度图像
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 高斯模糊
blurred_img = cv2.GaussianBlur(gray_img, (5, 5), 0)
# Canny边缘检测
edges = cv2.Canny(blurred_img, 50, 150)
# 查找轮廓
contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
# 绘制轮廓并分类形状
contour_img = img.copy()
for contour in contours:
# 计算轮廓面积
area = cv2.contourArea(contour)
# 计算轮廓周长
perimeter = cv2.arcLength(contour, True)
# 近似轮廓为多边形
epsilon = 0.02 * perimeter
approx = cv2.approxPolyDP(contour, epsilon, True)
# 获取轮廓顶点数目
num_vertices = len(approx)
# 根据顶点数目判断形状
shape = 'Unknown'
if num_vertices == 3:
shape = 'Triangle'
elif num_vertices == 4:
# 判断是否为正方形或矩形
x, y, w, h = cv2.boundingRect(approx)
aspect_ratio = w / float(h)
if 0.95 < aspect_ratio < 1.05:
shape = 'Square'
else:
shape = 'Rectangle'
elif num_vertices == 5:
shape = 'Pentagon'
elif num_vertices == 6:
shape = 'Hexagon'
else:
# 对于顶点数目大于6的形状,可以根据周长面积比等特征进一步分类
# 例如,圆形可以通过周长面积比接近某个阈值来判断
if 4 * 3.14 * (area / 3.14) ** 0.5 / perimeter > 0.8 and 4 * 3.14 * (area / 3.14) ** 0.5 / perimeter < 1.2:
shape = 'Circle'
else:
shape = 'Other Polygon'
# 在图像上标注形状名称和顶点数目
M = cv2.moments(contour)
if M['m00'] != 0:
cX = int(M['m10'] / M['m00'])
cY = int(M['m01'] / M['m00'])
else:
cX, cY = 0, 0
# 绘制形状名称和顶点数目
cv2.putText(contour_img, f'{shape} ({num_vertices} vertices)', (cX - 50, cY - 50), cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 2)
# 绘制轮廓(近似多边形)
cv2.drawContours(contour_img, [approx], -1, (0, 0, 255), 2)
# 显示结果图像
cv2.imshow('Shape Detection', contour_img)
cv2.waitKey(0)
cv2.destroyAllWindows()
九、总结
本文详细介绍了如何使用Python和OpenCV库实现图像形状检测。通过环境准备、图像预处理、边缘检测、轮廓查找、绘制轮廓及形状分类等步骤,展示了完整的图像形状检测流程。利用高斯模糊、Canny边缘检测和轮廓近似等技术,实现了对图像中不同形状的有效检测与分类。通过示例代码,读者可以快速掌握图像形状检测的基本方法和技巧,为工业自动化、机器人视觉等领域的实际应用提供有力支持。本文内容全面、步骤清晰,适合初学者及有一定基础的读者学习和参考。