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

如何让cv2.HoughLinesP仅检测垂直线,避免识别电车线架横线?

只检测电车架空线(垂直线)的优化方案

针对线架水平线误检测的问题,无需依赖效果不佳的腐蚀操作,以下两种方法可以直接解决:

方法一:过滤检测到的线条斜率

计算每条线段的斜率,只保留接近垂直的线条(斜率绝对值极大,或x坐标几乎无变化),彻底过滤水平线。

修改代码中处理lines的部分:

if lines is not None:
    # 垂直阈值:可根据实际场景调整,值越大要求线条越接近垂直
    vertical_threshold = 10
    for line in lines:
        x1, y1, x2, y2 = line[0]
        dx = x2 - x1
        if dx == 0:
            # 完全垂直的线段
            cv2.line(frame, (x1, y1), (x2, y2), (255, 0, 0), 5)
        else:
            slope = abs((y2 - y1) / dx)
            if slope > vertical_threshold:
                # 接近垂直的线段
                cv2.line(frame, (x1, y1), (x2, y2), (255, 0, 0), 5)

方法二:用垂直结构元素强化垂直线

如果想在边缘检测阶段就弱化水平线,可以替换你之前的正方形腐蚀核,改用垂直结构元素:

# 创建高瘦的垂直核,保留垂直线条,消除短水平线
kernel = np.ones((10,1), np.uint8)
edges = cv2.erode(edges, kernel, iterations=1)

完整优化后的代码

整合以上两种优化点的完整代码:

import cv2
import numpy as np
import window_names
import track_bars

vid = 'blackpool_tram_result.mp4'

cap = cv2.VideoCapture(vid)

frame_counter = 0

while (True):
    ret, frame = cap.read()

    frame_counter += 1

    if frame_counter == cap.get(cv2.CAP_PROP_FRAME_COUNT):
        frame_counter = 0
        cap.set(cv2.CAP_PROP_POS_FRAMES, 0)

    blank = np.zeros(frame.shape[:2], dtype='uint8')

    grey = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    output = np.empty(grey.shape, dtype=np.uint8)

    cv2.normalize(
        grey,
        output,
        alpha=0,
        beta=255,
        norm_type=cv2.NORM_MINMAX)

    hist = cv2.equalizeHist(output)

    track_bars.lower_threshold = cv2.getTrackbarPos("lower", window_names.window_canny)
    track_bars.upper_threshold = cv2.getTrackbarPos("upper", window_names.window_canny)
    track_bars.smoothing_neighbourhood = cv2.getTrackbarPos("smoothing", window_names.window_canny)
    track_bars.sobel_size = cv2.getTrackbarPos("sobel size", window_names.window_canny)

    track_bars.smoothing_neighbourhood = max(3, track_bars.smoothing_neighbourhood)
    if not (track_bars.smoothing_neighbourhood % 2):
        track_bars.smoothing_neighbourhood = track_bars.smoothing_neighbourhood + 1

    track_bars.sobel_size = max(3, track_bars.sobel_size)
    if not (track_bars.sobel_size % 2):
        track_bars.sobel_size = track_bars.sobel_size + 1

    smoothed = cv2.GaussianBlur(
        hist, (track_bars.smoothing_neighbourhood, track_bars.smoothing_neighbourhood), 0)

    edges = cv2.Canny(
        smoothed,
        track_bars.lower_threshold,
        track_bars.upper_threshold,
        apertureSize=track_bars.sobel_size)

    # 可选:用垂直结构元素腐蚀,强化垂直线,过滤短水平线
    kernel = np.ones((10,1), np.uint8)
    edges = cv2.erode(edges, kernel, iterations=1)

    rho = 1  # 霍夫网格的距离分辨率(像素)
    theta = np.pi / 180  # 霍夫网格的角度分辨率(弧度)
    threshold = 15  # 最小投票数
    minLineLength = 50  # 线段最小长度
    maxLineGap = 20  # 线段最大间隙
    line_image = np.copy(frame) * 0

    mask = cv2.rectangle(blank, (edges.shape[1]//2 + 150, edges.shape[0]//2 - 150), (edges.shape[1]//2 - 150, edges.shape[0]//2 - 300), 255, -1)

    masked = cv2.bitwise_and(edges,edges,mask=mask)

    lines = cv2.HoughLinesP(masked, rho, theta, threshold, np.array([]), minLineLength, maxLineGap)

    if lines is not None:
        # 过滤只保留垂直线段
        vertical_threshold = 10
        for line in lines:
            x1, y1, x2, y2 = line[0]
            dx = x2 - x1
            if dx == 0:
                cv2.line(frame, (x1, y1), (x2, y2), (255, 0, 0), 5)
            else:
                slope = abs((y2 - y1) / dx)
                if slope > vertical_threshold:
                    cv2.line(frame, (x1, y1), (x2, y2), (255, 0, 0), 5)

    lines_edges = cv2.addWeighted(frame, 0.8, line_image, 1, 0)

    cv2.imshow(window_names.window_hough, frame)
    cv2.imshow(window_names.window_canny, edges)
    cv2.imshow(window_names.window_mask, mask)
    cv2.imshow(window_names.window_masked_image, masked)

    key = cv2.waitKey(27)
    if (key == ord('x')) & 0xFF:
        break

cv2.destroyAllWindows()

调整建议

  • 可以根据实际视频场景修改vertical_threshold的值:值越大,对线条垂直程度的要求越高;值越小,允许的倾斜范围越大。
  • 若架空线存在轻微倾斜,可适当降低vertical_threshold,或调整腐蚀核的高度。

内容的提问来源于stack exchange,提问作者Isaac_E

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 01:01:51