You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何提取等轴测图中带内置箭头的粗长黑色线条?

提取图纸中带内置箭头的粗长黑线

我有一张元件的二维等轴测视图图纸,想要从中提取带有内置箭头的粗长黑色线条(非尺寸标注线)。但当前用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 14:02:57