基于OpenCV测量高温钢板绿线处宽度的可行方法咨询
高温钢板宽度测量(手动标记垂直线方案)
针对高温钢板边缘检测失效的问题,手动标记垂直线再测量间距是完全可行的,以下是具体实现方法和细节:
1. 鼠标交互式手动标记边缘
利用OpenCV的鼠标回调函数,实现点击标记钢板左右竖直边缘,自动绘制垂直线并计算间距:
import cv2 import numpy as np # 全局变量存储边缘x坐标、原始图像副本 edge_x = [] original_img = None display_img = None def mouse_click_handler(event, x, y, flags, param): global edge_x, display_img if event == cv2.EVENT_LBUTTONDOWN: # 绘制贯穿图像高度的垂直线(红色,厚度2) cv2.line(display_img, (x, 0), (x, display_img.shape[0]), (0, 0, 255), 2) edge_x.append(x) # 标注边缘序号 cv2.putText(display_img, f"Edge {len(edge_x)}", (x+10, 30), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2) # 加载目标图像 original_img = cv2.imread("high_temp_steel.jpg") display_img = original_img.copy() # 创建窗口并绑定鼠标事件 cv2.namedWindow("Edge Marker") cv2.setMouseCallback("Edge Marker", mouse_click_handler) # 交互循环 while True: cv2.imshow("Edge Marker", display_img) key = cv2.waitKey(1) & 0xFF # 按C重置标记,按Q退出计算 if key == ord("c"): display_img = original_img.copy() edge_x = [] elif key == ord("q"): break cv2.destroyAllWindows() # 计算宽度(需提前校准像素与实际尺寸的比例) if len(edge_x) == 2: pixel_width = abs(edge_x[1] - edge_x[0]) # 替换为你的校准比例,例:0.3mm/像素 actual_width = pixel_width * 0.3 print(f"钢板宽度:{round(actual_width, 2)} mm(像素宽度:{pixel_width})") else: print("请标记左右两个竖直边缘")
2. 结合预处理缩小标记范围(提升准确性)
高温钢板在绿线位置可能有特定亮度/颜色特征,可以先裁剪目标区域做预处理,减少标记误差:
- 裁剪绿线所在的水平区域(比如上下各20行)
- 对区域做灰度化+反阈值处理,突出钢板与背景的分界
- 在预处理后的区域上标记,更易定位边缘
关键代码片段:
# 假设绿线位于图像第250行附近,裁剪ROI roi = original_img[230:270, :] # 灰度化+反二值化(高温钢板偏亮,背景偏暗) gray_roi = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) _, thresh_roi = cv2.threshold(gray_roi, 180, 255, cv2.THRESH_BINARY_INV) # 显示预处理后的ROI用于标记 cv2.imshow("ROI for Marking", thresh_roi)
3. 批量处理的半自动优化
如果需要处理多张同场景图像,可以:
- 标记第一张图的边缘坐标,后续图像自动加载参考线
- 新增鼠标拖动事件,实现参考线的微调,提升批量处理效率
核心注意事项
- 必须提前校准像素-实际尺寸比例:用已知宽度的参照物拍摄同角度图像,计算每像素对应的实际长度
- 若图像存在透视畸变,需先做透视变换矫正,再进行标记测量
- 标记时尽量点击钢板边缘的中间位置,减少人为误差
内容的提问来源于stack exchange,提问作者Tony Stark
相关产品推荐
相关产品推荐

