树莓派3上的OpenCV多个USB摄像头

2024-05-13 19:22:53 发布

您现在位置:Python中文网/ 问答频道 /正文

我以前看过很多与此相关的问题,但都没有帮助。

我的设置:

  • 其中一个these
    • 它们以/dev/video0/dev/video1的形式出现
    • 图像为640 x 480
  • 覆盆子皮3
  • 拉斯宾·杰西
  • OpenCV 3.1.0版
  • Python2.7

对于任何一个摄像头,我都可以捕捉图像,并以相当不错的速度显示它们,而且延迟很小(偶尔会出现伪影)。

然而,当我尝试同时使用这两种方法时,我得到的帧速率可能是10倍(尽管帧之间的延迟似乎随着每帧的变化而变化很大),有各种令人讨厌的图像伪影(例如,见下文)和无法忍受的延迟量。

artifacts

问题不在于相机本身或设备上的USB带宽:当我将相机连接到我的Windows PC时,我能够以30帧/秒的速度捕获和显示,而不会出现任何视觉伪影和非常小的延迟。

据我所知,问题出在Pi硬件、驱动程序或OpenCV上。我不认为这是Pi硬件。。如果我能用两个相机达到一个相机的一半帧速率(我不明白为什么这不可能),并且没有难看的伪影,我会很高兴的。

有人有什么建议吗?我最终只是想把这两个摄像头的视频从我的Pi流到我的桌面上。如果有不涉及OpenCV的建议,我会全神贯注;我不会尝试在Pi上对图像进行任何渲染或操作,但是OpenCV是我发现的唯一一个能够相当快地捕捉图像的工具(当然是用一个相机)。

作为参考,我使用的简单python脚本如下:

import cv2
import numpy as np
import socket
import ctypes
import struct

cap = []
cap.append(cv2.VideoCapture(0))
cap.append(cv2.VideoCapture(1))

#grab a single frame from one camera
def grab(num):
    res, im = cap[num].read()
    return (res,im)

#grab a frame from each camera and stitch them
#side by side
def grabSBS():
    res, imLeft  = grab(1)
    #next line is for pretending I have 2 cameras
    #imRight = imLeft.copy()
    res, imRight = grab(0)
    imSBS = np.concatenate((imLeft, imRight), axis=1)
    return res,imSBS

###For displaying locally instead of streaming
#while(False):
#    res, imLeft = grab(0)
#    imRight = imLeft.copy()
#    imSBS = np.concatenate((imLeft, imRight), axis=1)
#    cv2.imshow("win", imSBS)
#    cv2.waitKey(20)

header_data = ctypes.create_string_buffer(12)

while(True):
    sck = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sck.bind(("10.0.0.XXX", 12321))

    sck.listen(1)

    while(True):
        (client, address) = sck.accept()
        print "Client connected:", address
        try:
            while(True):
            res,im = grabSBS()
            if(res):
                success, coded = cv2.imencode('.jpg', im)
                if (success):
                    height, width, channels = im.shape
                    size = len(coded)
                    struct.pack_into(">i", header_data , 0, width)
                    struct.pack_into(">i", header_data , 4, height)
                    struct.pack_into(">i", header_data , 8, size)
                    client.sendall(header_data .raw)
                    client.sendall(coded.tobytes())
        except Exception as ex:
            print "ERROR:", ex
            client.close()
            sck.close()
            exit()

更新:在初始化视频捕获对象之后添加以下几行代码,使它工作得更好:

cap[0].set(cv2.CAP_PROP_FPS, 15)
cap[1].set(cv2.CAP_PROP_FPS, 15)

这既降低了所需的带宽,又降低了openCV的工作负载。我还是每隔几帧就会收到那些可怕的艺术品,所以如果有人对此有意见,我很高兴听到。


Tags: 图像importdataressocketcv2opencvheader
1条回答
网友
1楼 · 发布于 2024-05-13 19:22:53

好吧,在花了大约5个小时与之抗争之后,我似乎找到了解决办法。

首先,显然OpenCV试图以每秒30帧的速度捕获,尽管我无法以每秒30帧的速度拉帧。我将视频捕获帧速率改为15帧/秒,视频变得更加平滑和快速。

cap[0].set(cv2.CAP_PROP_FPS, 15.0)
cap[1].set(cv2.CAP_PROP_FPS, 15.0)

不过,这并没有消除文物。我最终发现,如果我通过网络发送图像后再这样做,那么这些伪影就完全消失了。

相关问题 更多 >