如何使用OpenCV检测指针式仪表指针尖端并绘制表盘中心到尖端的连线
实现方案
首先先修复你现有代码里的几个明显错误:
- 变量名笔误:
date = np.uint16(np.around(circles))应该改为data = np.uint16(np.around(circles)),否则后续调用data会报未定义错误 - 语法错误:过滤小轮廓时的
continues改为continue - 颜色值写法错误:绘制轮廓时的
(0.255,0)改为(0,255,0)
指针尖端检测的核心逻辑非常简单:指针是从表盘中心向外延伸的细长结构,所以指针轮廓上距离表盘中心最远的点就是指针尖端,我们只需要遍历轮廓上的所有点计算到中心的距离,取最大值对应的点即可。
因为你是在裁剪后的ROI中检测的轮廓,轮廓的坐标是相对于ROI左上角的,需要加上ROI的全局偏移才能对应到原图坐标。
修改后的完整代码如下:
import numpy as np import cv2 import math img = cv2.imread('meter-3.jpg') # 预处理滤波 img = cv2.blur(img,(3,3)) kernel = np.ones((3,3), np.uint8) img_erosion = cv2.erode(img, kernel, iterations=1) img_dilation = cv2.dilate(img, kernel, iterations=1) gray = cv2.cvtColor(img_dilation, cv2.COLOR_BGR2GRAY) # 检测表盘圆心 circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1, 20, param1=50, param2=35, minRadius=10, maxRadius=46) data = np.uint16(np.around(circles)) for (x, y ,r) in data[0, :]: cv2.circle(img, (x, y), 2, (0, 255, 0), 1) # 绘制圆心 circles = circles.reshape(-1,3).astype(np.int16) for c in circles: x_c, y_c, R = c[0], c[1], c[2] roi_x1 = x_c - R roi_y1 = y_c - R roi_x2 = x_c + R roi_y2 = y_c + R # 裁剪表盘ROI ROI = img[roi_y1:roi_y2, roi_x1:roi_x2] ROI_blur = cv2.blur(ROI,(3,3)) edges_roi = cv2.Canny(ROI_blur, 320, 125) contours, hierarchy = cv2.findContours(edges_roi, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_NONE) for con in contours: x,y,w,h = cv2.boundingRect(con) # 过滤小轮廓 if w < 25 or h < 25: continue cv2.rectangle(ROI,(x,y),(x+w,y+h),(0,255,0),2,cv2.LINE_AA) # 计算指针尖端:遍历轮廓所有点,找距离圆心最远的点 max_dist = 0 tip_point = (0,0) for point in con: # 轮廓点转原图坐标:ROI偏移 + 轮廓相对坐标 px = roi_x1 + point[0][0] py = roi_y1 + point[0][1] # 计算到表盘中心的距离 dist = math.hypot(px - x_c, py - y_c) if dist > max_dist and dist < R: # 确保点在表盘范围内 max_dist = dist tip_point = (px, py) # 绘制圆心到尖端的连线 cv2.line(img, (x_c, y_c), tip_point, (0,0,255), 2) # 绘制尖端标记 cv2.circle(img, tip_point, 3, (255,0,0), -1) # 展示结果 cv2.imshow('Result', img) cv2.waitKey(0) cv2.destroyAllWindows()
补充说明:
- 代码里用
math.hypot直接计算两点欧氏距离,写法更简洁 - 增加了
dist < R的判断,避免选到表盘外的噪点 - 最后会在原图上用红色绘制中心到尖端的连线,蓝色标记尖端位置
- 如果指针轮廓检测不准,可以适当调整Canny的阈值参数,或者在裁剪ROI后做阈值二值化,突出指针和背景的差异,检测效果会更好
内容的提问来源于stack exchange,提问作者oaten64
相关产品推荐
相关产品推荐

