如何用OpenCV识别网绳粗细并准确测量其宽度与角度?
网绳宽度与角度测量方案
问题说明
需要处理含粗细两类网绳的图像,用OpenCV实现以下目标:
- 区分粗、细网绳
- 分别测量两类网绳的宽度与倾斜角度
此前尝试的轮廓最小外接矩形方法误测了网格间隙,需调整方案以准确识别网绳区域并测量绳宽。
稳定实现方案
核心思路
- 预处理优化:采用高斯降噪+自适应阈值分割,适配光照不均的场景,精准分离网绳与背景
- 形态学修正:用闭操作填充网绳区域的细小空隙,再用开操作消除噪声点,突出网绳的连通区域
- 轮廓筛选:通过面积、长宽比过滤掉网格间隙等无效轮廓,只保留网绳的有效区域
- 精准测量:对网绳轮廓计算最小外接矩形,取矩形短边为绳宽,矩形旋转角度为绳的倾斜角度
- 分类统计:设定合理宽度阈值,将网绳分为粗、细两类并统计数据
完整代码实现
import cv2 import numpy as np def measure_rope_properties(image): # 1. 图像预处理:灰度化 + 高斯降噪 gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY) blurred = cv2.GaussianBlur(gray, (5, 5), 0) # 2. 自适应阈值分割:适配光照不均,分割网绳与背景 thresh = cv2.adaptiveThreshold(blurred, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV, 11, 2) # 3. 形态学操作:闭操作填充网绳空隙,开操作去除噪声 kernel_close = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3)) closed = cv2.morphologyEx(thresh, cv2.MORPH_CLOSE, kernel_close, iterations=2) kernel_open = cv2.getStructuringElement(cv2.MORPH_RECT, (2, 2)) opened = cv2.morphologyEx(closed, cv2.MORPH_OPEN, kernel_open, iterations=1) # 4. 提取轮廓并筛选有效网绳区域 contours, _ = cv2.findContours(opened, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) # 筛选条件:面积大于阈值,长宽比符合网绳形态(避免间隙轮廓) min_area = 50 valid_contours = [] for cnt in contours: area = cv2.contourArea(cnt) if area < min_area: continue rect = cv2.minAreaRect(cnt) w, h = rect[1] if w == 0 or h == 0: continue aspect_ratio = max(w, h) / min(w, h) # 网绳的长宽比通常远大于1,过滤掉接近正方形的间隙轮廓 if aspect_ratio > 3: valid_contours.append(cnt) # 5. 测量网绳宽度、角度并分类 thick_ropes = [] # 存储(宽度, 角度) thin_ropes = [] width_threshold = 10 # 根据实际场景调整阈值 for cnt in valid_contours: rect = cv2.minAreaRect(cnt) center, (w, h), angle = rect # 绳宽取矩形的短边 rope_width = min(w, h) # 统一角度表示:转换为0-90度范围 if angle < -45: angle = 90 + angle # 分类 if rope_width > width_threshold: thick_ropes.append((round(rope_width, 2), round(angle, 2))) # 绘制粗绳矩形(红色) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(image, [box], 0, (0, 0, 255), 2) else: thin_ropes.append((round(rope_width, 2), round(angle, 2))) # 绘制细绳矩形(绿色) box = cv2.boxPoints(rect) box = np.int0(box) cv2.drawContours(image, [box], 0, (0, 255, 0), 2) return image, thick_ropes, thin_ropes if __name__ == "__main__": # 读取图像(注意路径分隔符用/或双反斜杠) image = cv2.imread('./pics/webFebric.png') if image is None: print("无法读取图像,请检查路径") exit() result_img, thick_data, thin_data = measure_rope_properties(image) # 显示结果 cv2.imshow('Rope Measurement Result', result_img) cv2.waitKey(0) cv2.destroyAllWindows() # 输出统计数据 print("粗绳(宽度, 角度):", thick_data) print("细绳(宽度, 角度):", thin_data)
关键细节说明
- 自适应阈值:相比固定阈值,能更好处理光照不均的网绳图像,避免局部过亮或过暗导致的分割错误
- 形态学操作:闭操作填充网绳上的细小断裂,开操作去除背景噪声,确保网绳区域的连通性
- 轮廓筛选:通过面积和长宽比过滤掉网格间隙——间隙的轮廓通常接近正方形,而网绳是长条状,长宽比远大于1
- 角度统一:将OpenCV最小外接矩形的角度转换为0-90度范围,更符合直观的倾斜角度认知
- 阈值调整:
width_threshold和min_area需根据实际图像的分辨率和网绳尺寸调整,确保分类准确
内容的提问来源于stack exchange,提问作者viktor2000
相关产品推荐
相关产品推荐

