Python 代码使用 OpenCV 库实现了从摄像头获取视频流,并在视频中检测特定颜色区域的边缘线条

发布于:2024-10-15 ⋅ 阅读:(63) ⋅ 点赞:(0)
import cv2
import numpy as np
#想和大神交朋友或想软件开发兼职接项目,请通过手机端搜小#程#序: "黄页小艺" 。
def extend_line_to_borders(x1, y1, x2, y2, width, height):
    # Compute the slope and intercept
    if x1 == x2 or abs(x2 - x1) < 1e-6:  # Vertical line
        return [(x1, 0), (x1, height)]
    else:
        slope = (y2 - y1) / (x2 - x1)
        intercept = y1 - slope * x1

        # Compute intersections with image borders
        y_at_x_min = int(intercept)  # x = 0
        y_at_x_max = int(slope * width + intercept)  # x = width

        if slope != 0:
            x_at_y_min = int(-intercept / slope)  # y = 0
            x_at_y_max = int((height - intercept) / slope)  # y = height
        else:
            x_at_y_min = 0
            x_at_y_max = width

        points = []
        if 0 <= y_at_x_min <= height:
            points.append((0, y_at_x_min))
        if 0 <= y_at_x_max <= height:
            points.append((width, y_at_x_max))
        if 0 <= x_at_y_min <= width:
            points.append((x_at_y_min, 0))
        if 0 <= x_at_y_max <= width:
            points.append((x_at_y_max, height))

        return points[:2]  # Return two intersection points

cap = cv2.VideoCapture(0)

if not cap.isOpened():
    print("无法打开摄像头")
    exit()

# Set camera properties
cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1280)
cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 720)
cap.set(cv2.CAP_PROP_AUTO_EXPOSURE, 0.25)
cap.set(cv2.CAP_PROP_EXPOSURE, -5)
cap.set(cv2.CAP_PROP_AUTO_WB, 0)
cap.set(cv2.CAP_PROP_WB_TEMPERATURE, 4000)

# Color range in HSV
lower_color = np.array([0, 0, 70])
upper_color = np.array([92, 70, 219])

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

    if not ret:
        print("无法接收到帧 (摄像头已断开)")
        break

    # Convert to HSV color space
    hsv = cv2.cvtColor(frame, cv2.COLOR_BGR2HSV)

    # Filter black and white color regions
    mask = cv2.inRange(hsv, lower_color, upper_color)

    # Use Canny edge detection
    edges = cv2.Canny(frame, 100, 300)

    # Hough Line Transform to detect lines
    lines = cv2.HoughLinesP(edges, rho=1, theta=np.pi/180, threshold=100, minLineLength=100, maxLineGap=10)

    # Get image dimensions
    height, width = frame.shape[:2]

    if lines is not None:
        if len(lines) == 1:
            # Only one line detected
            x1, y1, x2, y2 = lines[0][0]
            points = extend_line_to_borders(x1, y1, x2, y2, width, height)
            if len(points) == 2:
                cv2.line(frame, points[0], points[1], (0, 255, 0), 2)
        else:
            found_pair = False
            # Compute angles between pairs of lines
            for i in range(len(lines)):
                for j in range(i + 1, len(lines)):
                    x1_i, y1_i, x2_i, y2_i = lines[i][0]
                    x1_j, y1_j, x2_j, y2_j = lines[j][0]

                    # Direction vectors
                    v1 = np.array([x2_i - x1_i, y2_i - y1_i])
                    v2 = np.array([x2_j - x1_j, y2_j - y1_j])

                    # Normalize vectors
                    v1_norm = np.linalg.norm(v1)
                    v2_norm = np.linalg.norm(v2)
                    if v1_norm == 0 or v2_norm == 0:
                        continue  # Skip zero-length vectors

                    v1_unit = v1 / v1_norm
                    v2_unit = v2 / v2_norm

                    # Compute angle between vectors
                    dot_product = np.dot(v1_unit, v2_unit)
                    angle = np.arccos(dot_product) * 180 / np.pi  # In degrees

                    # Check if angle is approximately 90 degrees
                    if abs(angle - 90) < 10:  # Threshold of 10 degrees
                        # Extend and draw the lines
                        points_i = extend_line_to_borders(x1_i, y1_i, x2_i, y2_i, width, height)
                        points_j = extend_line_to_borders(x1_j, y1_j, x2_j, y2_j, width, height)
                        if len(points_i) == 2 and len(points_j) == 2:
                            cv2.line(frame, points_i[0], points_i[1], (0, 255, 0), 2)
                            cv2.line(frame, points_j[0], points_j[1], (0, 255, 0), 2)
                            found_pair = True
                            break
                if found_pair:
                    break
            else:
                # If no perpendicular pair found, you may choose to draw a single longest line or take other action
                pass

    # Display the frame with detected lines
    cv2.imshow('Camera', frame)

    # Press 'q' to exit
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()
 #想和大神交朋友或想软件开发兼职接项目,请通过手机端搜小#程#序: "黄页小艺" 。

上面 Python 代码使用 OpenCV 库实现了从摄像头获取视频流,并在视频中检测特定颜色区域的边缘线条,然后进行以下操作:

一、定义辅助函数

  1. extend_line_to_borders函数:
    • 该函数用于将给定的线段延长至图像的边界。
    • 首先计算线段的斜率和截距。如果线段是垂直的(斜率为无穷大或接近无穷大),则直接返回与图像上下边界的交点。
    • 对于非垂直线段,根据斜率和截距计算与图像四个边界的交点。
    • 最后返回两个交点(如果存在)。

二、摄像头设置与图像预处理

  1. 打开摄像头并设置摄像头属性:

    • 使用cv2.VideoCapture(0)打开默认摄像头。
    • 设置摄像头的分辨率为 1280x720,自动曝光为特定值,手动设置曝光值为 -5,关闭自动白平衡并设置白平衡温度为 4000。
  2. 定义颜色范围并进行图像处理:

    • 在 HSV 颜色空间中定义一个颜色范围,用于过滤出特定颜色(可能是接近黑色和白色的颜色范围)。
    • 将每一帧图像从 BGR 颜色空间转换为 HSV 颜色空间。
    • 使用cv2.inRange函数根据定义的颜色范围创建一个掩码,用于过滤出特定颜色区域。
    • 使用 Canny 边缘检测算法对图像进行边缘检测,得到边缘图像。

三、线条检测与绘制

  1. 使用 Hough 变换检测直线:

    • 通过cv2.HoughLinesP函数在边缘图像上检测直线。
  2. 处理检测到的直线:

    • 如果只检测到一条直线,使用extend_line_to_borders函数将该直线延长至图像边界,并在图像上绘制延长后的直线。
    • 如果检测到多条直线,计算每对直线之间的夹角。如果夹角接近 90 度(在 10 度误差范围内),将这两条直线延长至图像边界并绘制在图像上。如果没有找到垂直的直线对,则可以选择绘制最长的直线或采取其他操作。
  3. 显示图像并等待退出:

    • 使用cv2.imshow函数显示带有检测到的直线的图像帧。
    • 当用户按下’q’键时,退出循环并释放摄像头资源,关闭所有窗口。

总体来说,这段代码实现了一个实时的视频处理程序,用于在摄像头捕获的视频中检测特定颜色区域的边缘,并找到垂直或接近垂直的直线对,将其延长至图像边界并绘制在图像上。#想和大神交朋友或想软件开发兼职接项目,请通过手机端搜小#程#序: “黄页小艺” 。


网站公告

今日签到

点亮在社区的每一天
去签到