如何提取等轴测图中带内置箭头的粗长黑色线条?
提取图纸中带内置箭头的粗长黑线
我有一张元件的二维等轴测视图图纸,想要从中提取带有内置箭头的粗长黑色线条(非尺寸标注线)。但当前用OpenCV编写的代码会识别出所有线条,包括细线、文字、括号等,无法实现目标。
现有代码
import cv2 import numpy as np inputImage = cv2.imread("iso.jpg") inputImageGray = cv2.cvtColor(inputImage, cv2.COLOR_BGR2GRAY) edges = cv2.Canny(inputImageGray, 150, 200, apertureSize=3) minLineLength = 30 maxLineGap = 5 lines = cv2.HoughLinesP( image=edges, rho=cv2.HOUGH_PROBABILISTIC, theta=np.pi / 180, threshold=30, minLineLength=minLineLength, maxLineGap=maxLineGap, ) for x in range(0, len(lines)): for x1, y1, x2, y2 in lines[x]: pts = np.array([[x1, y1], [x2, y2]], np.int32) cv2.polylines(inputImage, [pts], True, (0, 255, 0)) cv2.imshow("Result", inputImage) cv2.imshow("Edges", edges) cv2.waitKey(0)
改进方案
核心思路是先过滤细线、文字等干扰,再结合箭头特征筛选目标线条,分两步实现:
1. 预处理过滤粗线条区域
通过二值化、形态学闭运算和轮廓面积筛选,先剥离细线、文字这类小尺寸干扰,只保留粗线条的边缘信息:
- 二值化将黑色线条转为前景;
- 闭运算填补粗线条的间隙,强化线条完整性;
- 轮廓面积过滤,剔除面积过小的干扰轮廓。
2. 线条筛选与箭头特征检测
在预处理后的粗线条边缘图上,用HoughLinesP检测线条,再通过以下规则筛选:
- 调大最小线条长度,过滤短线条(如文字笔画、括号);
- 检查线条端点附近的区域,统计黑色像素占比,判断是否存在箭头的三角形结构。
完整改进代码
import cv2 import numpy as np def filter_thick_lines(input_img): # 转灰度并二值化,黑色线条为前景 gray = cv2.cvtColor(input_img, cv2.COLOR_BGR2GRAY) _, binary = cv2.threshold(gray, 127, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU) # 结构元素尺寸可根据实际图纸线条粗细调整 kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (10, 3)) # 闭运算填补线条间隙,突出粗线条 closed = cv2.morphologyEx(binary, cv2.MORPH_CLOSE, kernel) # 提取轮廓,过滤小面积干扰 contours, _ = cv2.findContours(closed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE) thick_mask = np.zeros_like(binary) for cnt in contours: if cv2.contourArea(cnt) > 200: # 面积阈值按需调整 cv2.drawContours(thick_mask, [cnt], -1, 255, thickness=cv2.FILLED) # 提取粗线条的边缘 thick_edges = cv2.Canny(thick_mask, 50, 150) return thick_edges def detect_arrow_lines(edges, original_img): minLineLength = 80 # 调大最小长度过滤短线条 maxLineGap = 10 lines = cv2.HoughLinesP( image=edges, rho=1, theta=np.pi/180, threshold=40, minLineLength=minLineLength, maxLineGap=maxLineGap ) result_img = original_img.copy() if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] line_length = np.sqrt((x2-x1)**2 + (y2-y1)**2) if line_length < minLineLength: continue # 检查线条端点附近的箭头区域 end_x, end_y = x2, y2 # 取端点周围15x15的区域,尺寸按需调整 roi_y1, roi_y2 = max(0, end_y-15), min(original_img.shape[0], end_y+15) roi_x1, roi_x2 = max(0, end_x-15), min(original_img.shape[1], end_x+15) roi = original_img[roi_y1:roi_y2, roi_x1:roi_x2] # 统计roi内黑色像素占比,箭头区域黑色占比更高 roi_gray = cv2.cvtColor(roi, cv2.COLOR_BGR2GRAY) _, roi_bin = cv2.threshold(roi_gray, 127, 255, cv2.THRESH_BINARY_INV) black_ratio = np.sum(roi_bin == 255) / (roi.shape[0] * roi.shape[1]) if black_ratio > 0.15: # 占比阈值按需调整 cv2.polylines(result_img, [(x1,y1),(x2,y2)], False, (0,255,0), 2) return result_img # 主执行流程 inputImage = cv2.imread("iso.jpg") thick_edges = filter_thick_lines(inputImage) result = detect_arrow_lines(thick_edges, inputImage) cv2.imshow("Thick Edges", thick_edges) cv2.imshow("Target Lines", result) cv2.waitKey(0) cv2.destroyAllWindows()
注意事项
- 结构元素尺寸、面积阈值、线条最小长度、箭头区域尺寸及占比阈值,都需要根据实际图纸的线条粗细、箭头大小调整;
- 如果箭头特征不明显,可进一步用轮廓匹配(匹配三角形轮廓)替代像素占比统计,提升准确性。
内容的提问来源于stack exchange,提问作者forDeFan
相关产品推荐
相关产品推荐

