如何在Python中使用OpenCV给视频流应用多边形掩膜?

-1 投票
1 回答
44 浏览
提问于 2025-04-14 16:10

我正在用Python创建一个安全摄像头停车位检测系统,用户可以手动定义每个停车位的边界,这样系统就能更灵活。这个脚本可以让用户创建每个停车位的边界,效果很好,最后会把这些形状输出成一个字典数组,每个字典里包含了形状中每个点的x和y坐标。

我已经能够通过以下代码实现多边形的遮罩效果,比如这个图:this

img2 = cap # background image
plain = Image.new('L', (cap.shape[1], cap.shape[0]),0) # plain black image
polygon = [(shapes[i]['x1'], shapes[i]['y1']), (shapes[i]['x2'], shapes[i]['y2']), (shapes[i]['x3'], shapes[i]['y3']), (shapes[i]['x4'], shapes[i]['y4'])]
ImageDraw.Draw(plain).polygon(polygon, outline=1, fill=1)
mask = np.array(plain)
masked_img = cv.bitwise_and(img2, img2, mask = mask)
cv.imshow('d',masked_img)

我的目标是为用户输入的每个形状创建一个单独的遮罩,使用图像处理和Canny算法来判断是否有车停在这个遮罩内,然后再处理下一个停车位。这个过程会对每个停车位重复进行,只要有实时视频流。我在猜测PIL的指令可能会干扰视频流?

这是我到目前为止写的代码:

while True:
    while i<len(shapes):
        ret, frame = cap.read()
        blank = np.zeros((round(cap.get(3)), round(cap.get(4))))
        polygon = [(shapes[i]['x1'], shapes[i]['y1']), (shapes[i]['x2'], shapes[i]['y2']), (shapes[i]['x3'], shapes[i]['y3']), (shapes[i]['x4'], shapes[i]['y4'])]
        ImageDraw.Draw(blank).polygon(polygon, outline=1, fill=1)
        mask = np.array(blank)
        masked_img = cv.bitwise_and(frame, frame, mask = mask)

接下来我该怎么做呢?谢谢!

我写的代码目前出现了以下错误:

Traceback (most recent call last):
  File "Python\Python311\Lib\site-packages\PIL\ImageDraw.py", line 843, in Draw
    return im.getdraw(mode)
           ^^^^^^^^^^
AttributeError: 'numpy.ndarray' object has no attribute 'getdraw'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "my workspace\mycode.py", line 38, in <module>
    ImageDraw.Draw(blank).polygon(polygon, outline=1, fill=1)
    ^^^^^^^^^^^^^^^^^^^^^
  File "Python\Python311\Lib\site-packages\PIL\ImageDraw.py", line 845, in Draw
    return ImageDraw(im, mode)
           ^^^^^^^^^^^^^^^^^^^
  File "Python\Python311\Lib\site-packages\PIL\ImageDraw.py", line 62, in __init__
    im.load()
    ^^^^^^^
AttributeError: 'numpy.ndarray' object has no attribute 'load'

1 个回答

0

我建议使用numpy的切片功能来裁剪图像,因为使用cv.bitwise_and会增加计算负担。下面是一个简单的代码示例。

import cv2
import numpy as np

img = cv2.imread('top-view-parking-lot.jpg')

while True:
    roi = cv2.selectROI(img)
    print("ROI coordinates: ", roi)
    x, y, w, h = roi
    roi = img[y:y+h, x:x+w]

    edges = cv2.Canny(roi, 50, 150)

    edge_pixels = np.sum(edges > 0)
    print("Number of edge pixels: ", edge_pixels)

    if edge_pixels > 100: # Adjust this threshold as image quality varies
        print("Car detected!")
    else:
        print("No car detected.")

    cv2.imshow('ROI', roi)
    cv2.imshow('Edges', edges)
    if cv2.waitKey(0) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()

下面是一些例子,展示了代码在空停车位和占用停车位时的输出效果。

空停车位的例子:

没有检测到车

占用停车位的例子:

检测到车

如果你还有其他问题,欢迎随时留言。

撰写回答