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

基于OpenCV的视频帧十字激光线检测技术问题

问题描述

我有一支投射红色十字形状的激光笔,目标是编写Python代码,从IP Webcam推流的手机摄像头视频源中检测十字的两条线条。

单张图片检测问题

先尝试从单张图片中检测线条,但代码检测出大量多余线条,而非十字的两条主线:

# 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()

视频流检测问题

切换到视频源检测时,完全无法检测到任何线条,对应代码如下:

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()

解决方案

针对红色激光十字的特性,从颜色过滤入手精准提取激光区域,再结合边缘检测和直线筛选,可有效去除杂线并解决视频流检测失效问题。

核心优化方向

  • 用HSV色彩空间提取红色区域,避开背景干扰
  • 形态学操作去除红色区域的噪声点
  • 筛选水平/垂直方向的线条(十字激光的典型角度)
  • 调整直线检测参数,只保留符合激光长度特征的线条

改进后的单张图片检测代码

import numpy as np
import cv2 as cv

# 读取图片
image = cv.imread("input.jpg")
if image is None:
    print("无法读取图片")
    exit()

# 转换到HSV色彩空间,提取红色激光区域
hsv = cv.cvtColor(image, cv.COLOR_BGR2HSV)
# 红色在HSV中分为两段(色相通道为环形)
lower_red1 = np.array([0, 120, 70])
upper_red1 = np.array([10, 255, 255])
lower_red2 = np.array([170, 120, 70])
upper_red2 = np.array([180, 255, 255])
mask1 = cv.inRange(hsv, lower_red1, upper_red1)
mask2 = cv.inRange(hsv, lower_red2, upper_red2)
red_mask = cv.bitwise_or(mask1, mask2)

# 形态学操作去噪:闭运算补缺口,开运算除小点
kernel = np.ones((3,3), np.uint8)
red_mask = cv.morphologyEx(red_mask, cv.MORPH_CLOSE, kernel)
red_mask = cv.morphologyEx(red_mask, cv.MORPH_OPEN, kernel)

# 提取红色区域的边缘
edges = cv.Canny(red_mask, 50, 150)

# 霍夫直线检测,设置合理参数过滤短线
lines = cv.HoughLinesP(
    edges,
    rho=1,
    theta=np.pi/180,
    threshold=30,
    minLineLength=80,
    maxLineGap=20
)

# 只保留水平或垂直线条(角度误差±10度内)
if lines is not None:
    for x1,y1,x2,y2 in lines[:,0]:
        angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi
        # 水平(0/180度)或垂直(90/270度)
        if (abs(angle) < 10 or abs(angle - 180) < 10) or (abs(angle - 90) < 10 or abs(angle - 270) < 10):
            cv.line(image, (x1,y1), (x2,y2), (0,255,0), 2)

cv.imshow("十字检测结果", image)
cv.waitKey(0)
cv.destroyAllWindows()

改进后的视频流检测代码

import numpy as np
import cv2 as cv

# 替换为你的IP Webcam推流地址
cap = cv.VideoCapture("http://192.168.1.33:8080/video")
if not cap.isOpened():
    print("无法打开视频流")
    exit()

while True:
    ret, frame = cap.read()
    if not ret:
        print("无法获取视频帧")
        break
    
    # 缩放帧以减少计算量
    frame = cv.resize(frame, (640, 480))
    
    # 提取红色激光区域
    hsv = cv.cvtColor(frame, cv.COLOR_BGR2HSV)
    lower_red1 = np.array([0, 120, 70])
    upper_red1 = np.array([10, 255, 255])
    lower_red2 = np.array([170, 120, 70])
    upper_red2 = np.array([180, 255, 255])
    mask1 = cv.inRange(hsv, lower_red1, upper_red1)
    mask2 = cv.inRange(hsv, lower_red2, upper_red2)
    red_mask = cv.bitwise_or(mask1, mask2)
    
    # 形态学去噪
    kernel = np.ones((3,3), np.uint8)
    red_mask = cv.morphologyEx(red_mask, cv.MORPH_CLOSE, kernel)
    red_mask = cv.morphologyEx(red_mask, cv.MORPH_OPEN, kernel)
    
    # 边缘检测
    edges = cv.Canny(red_mask, 50, 150)
    
    # 霍夫直线检测
    lines = cv.HoughLinesP(
        edges,
        rho=1,
        theta=np.pi/180,
        threshold=20,
        minLineLength=60,
        maxLineGap=15
    )
    
    # 筛选水平/垂直线条
    if lines is not None:
        for x1,y1,x2,y2 in lines[:,0]:
            angle = np.arctan2(y2 - y1, x2 - x1) * 180 / np.pi
            if (abs(angle) < 10 or abs(angle - 180) < 10) or (abs(angle - 90) < 10 or abs(angle - 270) < 10):
                cv.line(frame, (x1,y1), (x2,y2), (0,255,0), 2)
    
    cv.imshow("激光十字实时检测", frame)
    if cv.waitKey(1) == ord('q'):
        break

cap.release()
cv.destroyAllWindows()

关键说明

  1. 颜色过滤:HSV空间比RGB更适合颜色提取,红色分两段是因为色相通道为0-180的环形,0和180附近均为红色区域
  2. 形态学操作:闭运算填补激光线条的小缺口,开运算去除背景中的红色噪点
  3. 角度筛选:十字激光多为水平/垂直,通过计算线条角度,过滤掉倾斜的杂线
  4. 参数调整:可根据实际场景调整minLineLength、maxLineGap和阈值,适配不同距离下的激光线条长度

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 19:07:09