简介:本文以OpenCV为核心,从基础理论到代码实现,系统讲解硬币检测的完整流程,涵盖图像预处理、边缘检测、轮廓提取、特征匹配等关键技术,提供可复用的Python代码及优化建议。
硬币检测是计算机视觉领域的经典应用场景,其核心目标是通过图像处理技术识别并定位图像中的硬币,同时可扩展至计数、面值分类等高级功能。OpenCV作为开源计算机视觉库,提供了从图像加载到特征分析的全套工具链,是硬币检测的理想选择。本文将从零开始,逐步解析硬币检测的关键步骤,并附上完整代码实现。
opencv-python(核心库)、numpy(数值计算)、matplotlib(可视化)
pip install opencv-python numpy matplotlib
硬币检测的第一步是图像预处理,目的是增强目标特征并抑制噪声。关键步骤包括:
import cv2img = cv2.imread('coins.jpg')gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
Canny算法通过双阈值法检测图像边缘,参数调整直接影响检测效果:
edges = cv2.Canny(blurred, 50, 150) # 阈值需根据图像调整
使用cv2.findContours提取轮廓,并通过面积、长宽比等特征筛选硬币轮廓:
contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
min_area = 100 # 最小面积阈值coin_contours = []for cnt in contours:area = cv2.contourArea(cnt)if area > min_area:coin_contours.append(cnt)
通过cv2.minEnclosingCircle拟合硬币轮廓,获取圆心和半径:
for cnt in coin_contours:(x, y), radius = cv2.minEnclosingCircle(cnt)center = (int(x), int(y))radius = int(radius)cv2.circle(img, center, radius, (0, 255, 0), 2) # 绘制外接圆
对于复杂场景,霍夫圆变换可直接检测图像中的圆形:
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, dp=1, minDist=20,param1=50, param2=30, minRadius=10, maxRadius=100)if circles is not None:circles = np.uint16(np.around(circles))for i in circles[0, :]:cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)
针对复杂光照场景,可采用自适应阈值或CLAHE增强对比度:
clahe = cv2.createCLAHE(clipLimit=2.0, tileGridSize=(8, 8))enhanced = clahe.apply(gray)
通过半径或面积范围区分不同面值硬币:
def classify_coin(radius):if 10 < radius < 15:return "1元"elif 15 < radius < 20:return "5角"else:return "未知"
import cv2import numpy as npimport matplotlib.pyplot as pltdef detect_coins(image_path):# 1. 加载图像并预处理img = cv2.imread(image_path)gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)blurred = cv2.GaussianBlur(gray, (5, 5), 0)# 2. 边缘检测edges = cv2.Canny(blurred, 50, 150)# 3. 轮廓检测与筛选contours, _ = cv2.findContours(edges.copy(), cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)coin_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 100]# 4. 绘制结果for cnt in coin_contours:(x, y), radius = cv2.minEnclosingCircle(cnt)center = (int(x), int(y))radius = int(radius)cv2.circle(img, center, radius, (0, 255, 0), 2)cv2.putText(img, f"R:{radius}", (center[0]-20, center[1]-20),cv2.FONT_HERSHEY_SIMPLEX, 0.5, (255, 0, 0), 1)# 显示结果plt.figure(figsize=(12, 6))plt.subplot(121), plt.imshow(cv2.cvtColor(edges, cv2.COLOR_BGR2RGB)), plt.title('边缘检测')plt.subplot(122), plt.imshow(cv2.cvtColor(img, cv2.COLOR_BGR2RGB)), plt.title('检测结果')plt.show()detect_coins('coins.jpg')
本文从OpenCV基础操作入手,系统讲解了硬币检测的全流程,包括图像预处理、边缘检测、轮廓提取和特征分析。通过代码实现和优化建议,读者可快速构建自己的硬币检测系统。未来可进一步探索深度学习模型(如YOLO)在复杂场景中的应用,或结合多传感器数据提升检测鲁棒性。