Python Raspberry Pi 3上的OpenCV多USB摄像头
我已经看了很多以前的问题与此相关,没有一个有帮助 我的设置:Python Raspberry Pi 3上的OpenCV多USB摄像头,python,opencv,raspberry-pi,raspbian,Python,Opencv,Raspberry Pi,Raspbian,我已经看了很多以前的问题与此相关,没有一个有帮助 我的设置: 其中之一 它们显示为/dev/video0和/dev/video1 图像为640x480 树莓皮3 拉斯宾·杰西 OpenCV 3.1.0 Python 2.7 对于其中任何一个相机,我都可以捕获图像并以相当不错的速度显示它们,并且延迟最小(偶尔会出现瑕疵) 然而,当我尝试同时使用这两种方法时,我得到的帧速率可能是帧速率的十分之一(尽管帧之间的延迟似乎随着每一帧的变化而变化很大),有各种令人讨厌的图像伪影(例如,见下文)和无法
- 其中之一
- 它们显示为
和/dev/video0
/dev/video1
- 图像为640x480
- 它们显示为
- 树莓皮3
- 拉斯宾·杰西
- OpenCV 3.1.0
- Python 2.7
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()
更新:我在初始化VideoCapture对象后添加了以下几行代码,使其工作得更好:
cap[0].set(cv2.CAP_PROP_FPS, 15)
cap[1].set(cv2.CAP_PROP_FPS, 15)
这既降低了所需的带宽,也降低了openCV的工作负载。我仍然每隔几帧就收到这些可怕的伪影,所以如果有人对此提出建议,我很高兴听到这些建议。好吧,在花了大约5个小时与之斗争之后,我似乎找到了解决办法 首先,很明显,OpenCV试图以每秒30帧的速度拍摄,尽管我无法以每秒30帧的速度拍摄帧。我将视频捕获帧速率改为15 FPS,视频变得越来越平滑,越来越快
cap[0].set(cv2.CAP_PROP_FPS, 15.0)
cap[1].set(cv2.CAP_PROP_FPS, 15.0)
不过,这并没有消除这些文物。我最终发现,如果在通过网络发送图像后执行
del(im)
,伪影就会完全消失。相机图像是否已编码??如果使用####进行本地显示而不是流式显示,会发生什么情况?我不知道当OpenCV从驱动程序检索图像时,它们采取什么形式。VideoCapture.read()以Numpy ndarray格式返回图像,这是一种原始格式。然后我使用JPEG编码来缩小尺寸并通过网络发送。至于“####用于本地显示”位,当我使用它时,它会在Pi的显示器上显示视频。不过,该代码并没有同时使用两个摄像头,只是使用了一个摄像头,然后它复制图像,假装它有两个摄像头。当我使用它时,视频非常流畅。一些想法。。。我相信只有一个USB控制器,摄像头和网络接口必须共享,这可能是一个瓶颈。另外,你可以使用多线程,因为Pi有4个内核,可以让一个线程进行JPEG编码,或者让两个线程进行交替帧编码?只是一个想法。我的意思是从摄像机编码,以便pi必须解码它们,这可能是一个瓶颈。pc可能更快。你能尝试合并图像(例如,将两个图像合并到一个大图像)并仅对单个图像进行编码+流式处理吗?和/或在编码/流式传输之前尝试调整图像大小(更小),以便更好地了解瓶颈可能在哪里?这看起来像是通过网络异步发送,并且您在发送或复制图像时正在更改位?但这意味着在图像完全发送之前删除它,所以这可能不是原因,或者你只是幸运的一个有趣的想法。。我没有考虑到它可能是异步进行的。我显然认为sendall()
是一个阻塞调用。无论哪种方式,我都体验到了这些伪影,即使我只是在本地显示图像——根本不使用网络。当不使用网络时,python代码没有一个是异步的,因此两个线程同时在同一个缓冲区上运行应该不会有任何问题,除非OpenCV做了一些不正常的事情,并在它交给我之后继续写入Numpy ndarray。相机可能会连续写入缓冲区,但通常情况下,这不应该是您访问的缓冲区。