使用OpenCV检测刻度盘上模糊的小三角标识
温控箱刻度盘轻微凸起三角定位方案
径向灰度扫描法
借助已知的刻度盘中心,沿全角度径向扫描像素灰度。由于三角是轻微凸起,其位置的灰度会与周围刻度形成明显差异。通过对比相邻径向的灰度变化,定位突变点即为三角位置:import cv2 import numpy as np center = (cx, cy) # 已获取的刻度盘中心坐标 radius = 100 # 刻度盘半径(根据实际调整) angle_step = 1 # 扫描步长(单位:度) max_gray_diff = 0 target_angle = 0 prev_gray = 0 for angle in range(0, 360, angle_step): rad = np.deg2rad(angle) # 计算当前角度下的径向坐标 x = int(center[0] + radius * np.cos(rad)) y = int(center[1] + radius * np.sin(rad)) # 取3x3区域平均灰度,避免单像素噪点干扰 gray_val = np.mean(cv2.cvtColor(img[y-1:y+2, x-1:x+2], cv2.COLOR_BGR2GRAY)) if angle > 0: gray_diff = abs(gray_val - prev_gray) if gray_diff > max_gray_diff: max_gray_diff = gray_diff target_angle = angle prev_gray = gray_val # 转换为三角点坐标 tri_x = int(center[0] + radius * np.cos(np.deg2rad(target_angle))) tri_y = int(center[1] + radius * np.sin(np.deg2rad(target_angle)))轮廓极径极值分析
针对已获取的刻度盘轮廓,将轮廓点转换为以中心为原点的极坐标,计算每个点的极径。三角作为凸起,其极径会显著大于(或小于)周围刻度的轮廓点,找到局部极值点即可定位:import numpy as np import cv2 contour = ... # 已获取的刻度盘轮廓 center = (cx, cy) # 刻度盘中心 polar_data = [] # 转换所有轮廓点为极坐标 for point in contour: x, y = point[0] dx = x - center[0] dy = y - center[1] rad = np.sqrt(dx**2 + dy**2) angle = np.arctan2(dy, dx) polar_data.append((angle, rad)) # 按角度排序,便于连续分析 polar_data.sort(key=lambda item: item[0]) # 遍历寻找局部极径最大值(凸起对应更大极径) tri_x, tri_y = 0, 0 for i in range(1, len(polar_data)-1): prev_rad = polar_data[i-1][1] curr_rad = polar_data[i][1] next_rad = polar_data[i+1][1] if curr_rad > prev_rad and curr_rad > next_rad: tri_angle = polar_data[i][0] tri_x = int(center[0] + curr_rad * np.cos(tri_angle)) tri_y = int(center[1] + curr_rad * np.sin(tri_angle)) break局部阈值化+连通域筛选
对刻度盘ROI进行局部阈值处理,放大三角凸起与背景的差异,再通过连通域面积筛选定位三角:import cv2 center = (cx, cy) radius = 100 # 提取刻度盘ROI roi = img[center[1]-radius:center[1]+radius, center[0]-radius:center[0]+radius] gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) # 自适应阈值化,突出微小灰度差异 thresh = cv2.adaptiveThreshold(gray_roi, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 提取外部连通域 contours, _ = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选最小有效连通域(三角面积通常远小于刻度) min_area = float('inf') target_cnt = None for cnt in contours: area = cv2.contourArea(cnt) if 10 < area < min_area: # 过滤噪点和大轮廓 min_area = area target_cnt = cnt # 转换为全局坐标 if target_cnt is not None: x, y, w, h = cv2.boundingRect(target_cnt) tri_x = center[0] - radius + x + w//2 tri_y = center[1] - radius + y + h//2
内容的提问来源于stack exchange,提问作者Will
相关产品推荐
相关产品推荐

