从零开始详解OpenCV硬币检测

一、OpenCV环境搭建与基础准备

OpenCV(Open Source Computer Vision Library)是一个开源的计算机视觉库,支持Python、C++等多种语言。硬币检测作为计算机视觉的入门级应用,适合初学者理解图像处理的基本流程。

1.1 环境配置

  • Python安装:推荐使用Python 3.8+,可通过Anaconda或官方安装包配置。
  • OpenCV安装:通过pip安装OpenCV-Python包(pip install opencv-python),若需扩展功能可安装opencv-contrib-python
  • 依赖库:NumPy(数值计算)、Matplotlib(可视化)需同步安装。

1.2 基础图像操作

OpenCV以NumPy数组形式存储图像,支持BGR(蓝绿红)通道格式。以下代码展示图像的读取与显示:

  1. import cv2
  2. # 读取图像(支持JPG、PNG等格式)
  3. image = cv2.imread('coin.jpg')
  4. # 显示图像
  5. cv2.imshow('Original Image', image)
  6. cv2.waitKey(0)
  7. cv2.destroyAllWindows()

二、硬币检测核心流程

硬币检测的核心在于通过图像处理技术定位圆形物体,主要步骤包括预处理、边缘检测、轮廓提取与筛选。

2.1 图像预处理

2.1.1 灰度化

彩色图像包含冗余信息,转换为灰度图可提升处理效率:

  1. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

2.1.2 降噪

使用高斯模糊减少噪声干扰:

  1. blurred = cv2.GaussianBlur(gray, (5, 5), 0)

参数(5,5)为核大小,0表示根据核大小自动计算标准差。

2.2 边缘检测

Canny边缘检测通过双阈值法提取清晰边缘:

  1. edges = cv2.Canny(blurred, 50, 150)
  • 低阈值(50):抑制弱边缘。
  • 高阈值(150):保留强边缘。

2.3 霍夫圆变换检测

霍夫圆变换(HoughCircles)是检测圆形的经典算法,通过投票机制定位圆心与半径:

  1. circles = cv2.HoughCircles(
  2. blurred,
  3. cv2.HOUGH_GRADIENT,
  4. dp=1, # 分辨率倒数(1表示与输入图像相同)
  5. minDist=20, # 圆心最小距离
  6. param1=50, # Canny边缘检测高阈值
  7. param2=30, # 圆心检测阈值(越小检测越多)
  8. minRadius=10, # 最小半径
  9. maxRadius=50 # 最大半径
  10. )
  • 参数调优param2对结果影响显著,需根据图像调整。
  • 结果解析circles返回三维数组,格式为[x, y, radius]

2.4 轮廓提取与筛选(替代方案)

若霍夫变换效果不佳,可结合轮廓检测与几何筛选:

  1. # 二值化处理
  2. _, thresh = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY)
  3. # 查找轮廓
  4. contours, _ = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
  5. # 筛选近似圆形轮廓
  6. for cnt in contours:
  7. perimeter = cv2.arcLength(cnt, True)
  8. approx = cv2.approxPolyDP(cnt, 0.04 * perimeter, True)
  9. area = cv2.contourArea(cnt)
  10. if len(approx) > 8 and area > 100: # 多边形边数与面积阈值
  11. (x, y), radius = cv2.minEnclosingCircle(cnt)
  12. # 进一步筛选半径范围

三、完整代码示例

  1. import cv2
  2. import numpy as np
  3. def detect_coins(image_path):
  4. # 读取图像
  5. image = cv2.imread(image_path)
  6. if image is None:
  7. print("Error: Image not found.")
  8. return
  9. # 预处理
  10. gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
  11. blurred = cv2.GaussianBlur(gray, (5, 5), 0)
  12. # 霍夫圆检测
  13. circles = cv2.HoughCircles(
  14. blurred, cv2.HOUGH_GRADIENT, dp=1, minDist=20,
  15. param1=50, param2=30, minRadius=10, maxRadius=50
  16. )
  17. # 绘制结果
  18. if circles is not None:
  19. circles = np.uint16(np.around(circles))
  20. for i in circles[0, :]:
  21. cv2.circle(image, (i[0], i[1]), i[2], (0, 255, 0), 2)
  22. cv2.circle(image, (i[0], i[1]), 2, (0, 0, 255), 3)
  23. # 显示结果
  24. cv2.imshow('Detected Coins', image)
  25. cv2.waitKey(0)
  26. cv2.destroyAllWindows()
  27. # 调用函数
  28. detect_coins('coin.jpg')

四、优化与扩展

4.1 参数自适应

通过图像分析动态调整参数(如根据图像尺寸计算minRadiusmaxRadius)。

4.2 多硬币分类

结合面积与颜色信息区分不同面值硬币(需转换为HSV色彩空间进行颜色阈值分割)。

4.3 性能优化

  • 对大图像进行缩放处理。
  • 使用多线程加速处理。

五、常见问题与解决方案

  1. 漏检/误检:调整param2和半径范围,或结合形态学操作(如膨胀)增强边缘。
  2. 光照不均:使用自适应阈值(cv2.adaptiveThreshold)替代全局阈值。
  3. 重叠硬币:需引入更复杂的分割算法(如分水岭算法)。

六、总结

本文从环境搭建到完整代码实现,系统讲解了OpenCV硬币检测的流程。通过霍夫圆变换与轮廓分析的结合,可有效应对多数场景。实际应用中需根据具体需求调整参数,并考虑光照、遮挡等复杂因素。建议读者通过修改参数、替换测试图像深入理解算法原理。