基于Python与OpenCV(CV2)检测特定直线以判断零件正反
精准检测目标直线的可行方案
针对椭圆轮廓干扰下的特定直线检测,无需深度学习模型,可通过以下步骤优化OpenCV处理流程:
一、针对性预处理,过滤椭圆边缘干扰
椭圆的边缘通常是连续曲线,拆分成的线段细碎且灰度变化平缓,可通过预处理强化目标直线、弱化椭圆特征:
- 定向边缘检测:如果目标直线有固定方向(如水平/垂直),用
cv2.Sobel算子单独检测该方向的边缘,替代通用的Canny检测。比如检测水平直线时:
import cv2 import numpy as np img = cv2.imread("part_img.jpg", 0) # 水平边缘检测 sobel_x = cv2.Sobel(img, cv2.CV_64F, 1, 0, ksize=3) sobel_x = cv2.convertScaleAbs(sobel_x) # 二值化强化直线特征 _, binary = cv2.threshold(sobel_x, 50, 255, cv2.THRESH_BINARY)
- 形态学操作:用适配直线方向的细长结构元素做膨胀,连接直线断裂部分,再用腐蚀去除椭圆的细碎边缘:
# 水平结构元素,适配水平直线 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (15, 1)) processed = cv2.dilate(binary, kernel, iterations=1) processed = cv2.erode(processed, kernel, iterations=1)
二、精细化HoughLinesP参数,过滤误检线段
HoughLinesP的参数直接决定检测结果,针对椭圆的短线段干扰,重点调整以下参数:
minLineLength:设置为目标直线长度的最小阈值,过滤椭圆拆分出的短弧线段maxLineGap:根据直线连续性设置,避免直线被拆分成多段theta:如果目标直线方向固定,限制角度范围(比如水平直线设为np.pi/2 ± 0.1)threshold:提高投票阈值,只保留高置信度的直线
示例代码:
lines = cv2.HoughLinesP( processed, rho=1, theta=np.pi/180, threshold=30, minLineLength=80, # 目标直线最小长度,按需调整 maxLineGap=10, # 可选:限制角度范围(水平直线示例) theta_min=np.pi/2 - 0.17, # 对应80度 theta_max=np.pi/2 + 0.17 # 对应100度 )
三、基于轮廓特征二次过滤
先提取图像中的所有轮廓,通过几何特征区分直线和椭圆:
- 提取并过滤小面积轮廓:
contours, _ = cv2.findContours(processed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 过滤面积过小的干扰轮廓 valid_contours = [cnt for cnt in contours if cv2.contourArea(cnt) > 100]
- 对轮廓做直线拟合,通过长宽比筛选直线:
target_lines = [] for cnt in valid_contours: # 拟合直线 [vx, vy, x, y] = cv2.fitLine(cnt, cv2.DIST_L2, 0, 0.01, 0.01) # 计算轮廓最小外接矩形的长宽比 rect = cv2.minAreaRect(cnt) width, height = rect[1] # 长宽比大于5判定为直线(按需调整阈值) if max(width, height) / min(width, height) > 5: target_lines.append((vx, vy, x, y))
四、结合零件定位信息做位置校验
利用已完成的零件定位结果,校验检测到的直线是否在预设区域内:
- 计算直线到零件中心的距离,只保留距离在合理范围内的直线
- 检查直线是否完全落在零件的外接框内,过滤框外的干扰线条
内容的提问来源于stack exchange,提问作者Moritz Pfennig
相关产品推荐
相关产品推荐

