如何使`cv2.HoughLinesP` 仅检测垂直线?

huangapple go评论59阅读模式
英文:

How to make cv2.HoughLinesP detect only vertical lines?

问题

我尝试使我的程序仅检测火车/电车上方的电线,但当电线夹持装置出现在画面中时,它会检测到它们的水平线,这是我不想要的。我不知道是否有人知道如何使它只检测垂直线。我尝试使用cv2.erodenp.ones来仅显示垂直线,但似乎没有取得任何进展。有人提到HoughLines可以使线只保持垂直,但我不知道这是否正确。以下是我的代码:

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)

    rho = 1  # Hough网格的像素距离分辨率
    theta = np.pi / 180  # Hough网格的弧度角分辨率
    threshold = 15  # Hough网格单元中的最小投票数(交点数)
    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:
        for x1, y1, x2, y2 in lines[0]:
            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()
英文:

I'm trying to make it so my programme only detects an overhead wire on a train/tram but when the wire holders come into frame it detects the horizontal line of them which I don't want. I didn't know if anyone knew how to make it so it will only detect vertical lines. I tried using cv2.erode along with np.ones to only show vertical lines but I couldn't seem to get anywhere with that. Someone did mention that HoughLines can be made so there just vertical but I don't know if that's true or not. Here's my code:

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)
rho = 1  # distance resolution in pixels of the Hough grid
theta = np.pi / 180  # angular resolution in radians of the Hough grid
threshold = 15  # minimum number of votes (intersections in Hough grid cell)
minLineLength = 50  # minimum number of pixels making up a line
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:
for x1, y1, x2, y2 in lines[0]:
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()

答案1

得分: 3

HoughLines() 允许您配置最小和最大线角度以进行检测。您可以在此处查看详细信息。

但是,HoughLinesP 不具备此选项。您可以对HoughLinesP 输出的线进行过滤。根据文档的描述:

输出线的向量。每条线由一个4元素向量表示
(x1, y1, x2, y2),其中(x1, y1)和(x2, y2)是每个检测到的线段的结束点。

因此,只需获取起始点(x1, y1)和结束点(x2, y2),然后使用简单的数学计算来计算角度。

通过获取结果,您可以根据所需的角度值对每条线进行过滤。

英文:

HoughLines() gives you the ability to configure minimum and maximun line angles to detect. You can check here for details.

However, HoughLinesP doesn't have this option. What you can do is that filtering lines which HoughLinesP gives as output. According to the documentation:

> Output vector of lines. Each line is represented by a 4-element vector
> (x1,y1,x2,y2) , where (x1,y1) and (x2,y2) are the ending points of
> each detected line segment.

So just get the starting(x1,y1) and ending(x2,y2) points and calculate the angles with a simple math.

如何使`cv2.HoughLinesP` 仅检测垂直线?

By getting the results you can filter each line according to the desired angle value.

huangapple
  • 本文由 发表于 2023年2月16日 18:29:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/75470933.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定