使用 OpenCV 从视频帧中进行线条检测

问题描述 投票:0回答:1

我有一个可以投射红十字形状的激光笔。我的目标是编写一个 python 代码来检测视频源中的这两条投影线。我使用手机摄像头作为源,视频通过网络 IP 源进行流式传输。

1

首先,我想在尝试使用视频输入之前检测单个图像中的线条。我在下面编写了 python 代码,结果我得到了多行而不是十字上的主线。您可以看到输入和输出图像。我想去掉不需要的线并只检测十字上的主要两条线。

# import necessary modules
import numpy as np
import urllib.request
import cv2 as cv

# read the image
with open("input.jpg", "rb") as image:
    f = image.read()

    # convert to byte array
    bytef = bytearray(f)

    # convert to numpy array
    image = np.asarray(bytef)

    # Convert image to grayscale
    gray = cv.imdecode(image, 1)

    # Use canny edge detection
    edges = cv.Canny(gray, 50, 150, apertureSize=3) # default apertureSize: 3

    # Apply HoughLinesP method to
    # to directly obtain line end points
    lines_list = []
    lines = cv.HoughLinesP(
        edges,  # Input edge image
        1,  # Distance resolution in pixels
        np.pi / 180,  # Angle resolution in radians
        threshold=100,  # Min number of votes for valid line (default: 100)
        minLineLength=50,  # Min allowed length of line
        maxLineGap=10  # Max allowed gap between line for joining them (default: 10)
    )

    if lines is not None:
        # Iterate over points
        for points in lines:
            # Extracted points nested in the list
            x1, y1, x2, y2 = points[0]
            # Draw the lines joing the points
            # On the original image
            cv.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
            # Maintain a simples lookup list for points
            lines_list.append([(x1, y1), (x2, y2)])

    # display image
    cv.imshow("Image", image)
    cv.waitKey()

2

当我用视频源尝试时,它根本没有检测到任何线条。我用来传输视频的移动应用程序是“IP Webcam”。你可以在下面看到我的代码。

import numpy as np
import cv2 as cv

# replace with your own IP provided in ip webcam mobile app "IPv4_address/video"
cap = cv.VideoCapture("http://192.168.1.33:8080/video")

while(True):
    _, image = cap.read()

    # Resize the image
    image = cv.resize(image, (500, 500))

    # Convert image to grayscale
    gray = cv.cvtColor(image, cv.COLOR_BGR2GRAY)

    # Use canny edge detection
    edges = cv.Canny(gray, 50, 150, apertureSize=3)

    # Apply HoughLinesP method to
    # to directly obtain line end points
    lines_list = []
    lines = cv.HoughLinesP(
        edges,  # Input edge image
        1,  # Distance resolution in pixels
        np.pi / 180,  # Angle resolution in radians
        threshold=10,  # Min number of votes for valid line (default: 100)
        minLineLength=5,  # Min allowed length of line
        maxLineGap=200  # Max allowed gap between line for joining them (default: 10)
    )

    if lines is not None:
        # Iterate over points
        for points in lines:
            # Extracted points nested in the list
            x1, y1, x2, y2 = points[0]
            # Draw the lines joing the points
            # On the original image
            cv.line(image, (x1, y1), (x2, y2), (0, 255, 0), 2)
            # Maintain a simples lookup list for points
            lines_list.append([(x1, y1), (x2, y2)])

    cv.imshow('Livestream', image)
    if cv.waitKey(1) == ord('q'):
        break

cap.release()
cv.destroyAllWindows()


python opencv computer-vision hough-transform straight-line-detection
1个回答
0
投票

我之前也遇到过同样的问题,

HouhLinesP
这个函数迫切需要非最大抑制。

我的答案不是完整的答案,但您可以使用下面的函数来消除重复的行。方法如下:

  1. 找到所有线的起点和终点
  2. 这些点在屏幕上(x 在 [0,width] 中,y 在 [0,height] 中)
  3. 比较每条线的起点和终点并消除重复。

您可以直接将

HoughLinesP
的输出提供给此函数。有什么问题请尽管问。

def findUniqueLines(lines):
    # Find start and end points of all lines and add them to list
    newlines = []
    for [[x1,y1,x2,y2]] in lines:
        if x1==x2:           #perfectly vertical line
            start = (x1,0)
            end = (x1,h)
    
        elif y1==y2:         #perfectly horizontal line
            start = (0,y1)
            end = (w,y1)
    
        else:                #lines with a slope                   
            m,n = numpy.polyfit((x1,x2),(y1,y2),deg=1) #line eq:y=mx+n

            if abs(m) > 1:          #vertical-like line
                start = (-n/m,0)
                end = ((h-n)/m,h)
            else:                   #horizontal-like line
                start = (0,m*0+n)
                end = (w,m*w+n)

        if start[0]*start[1]>=0 or end[0]*end[1]>=0:
            newlines.append([[start[0],start[1],end[0],end[1]]])

    #Comparing the start end points extract the unique lines 
    unique_lines = []
    unique_lines.append(newlines[0])
    for [[sx,sy,ex,ey]] in newlines:#iterate over all lines
        s = (sx,sy)
        e = (ex,ey)

        for [[sUx,sUy,eUx,eUy]] in unique_lines:#compare each with unique lines
            sU = (sUx,sUy)
            eU = (eUx,eUy)

            #If the start and end points are within 50px range its not a unique line
            if math.dist(s,sU)<50 and math.dist(e,eU)<50:
                break
        else:
            unique_lines.append([[sx,sy,ex,ey]])
    return unique_lines
© www.soinside.com 2019 - 2024. All rights reserved.