我在 Raspberry Pi 3 上运行了简单的 python 脚本。该脚本负责打开视频设备并使用 MJPEG 将数据 (800x600) 流式传输到 HTTP 端点。当我收到此流时,我的 Raspberry Pi 核心之一可以 100% 工作。可以用多线程运行 OpenCV 吗?
这是我的代码
import cv2
from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
import time
import argparse
import socket as Socket
camera = None
def setUpCameraCV():
global camera
camera = cv2.VideoCapture(0)
class mjpgServer(BaseHTTPRequestHandler):
ip = None
hostname = None
def do_GET(self):
print('connection from:', self.address_string())
if self.ip is None or self.hostname is None:
self.ip, _ = 0.0.0.0
self.hostname = Socket.gethostname()
if self.path == '/mjpg':
self.send_response(200)
self.send_header('Cache-Control', 'no-cache')
self.send_header('Pragma', 'no-cache')
self.send_header('Connection', 'close')
self.send_header(
'Content-type',
'multipart/x-mixed-replace; boundary=mjpegstream'
)
self.end_headers()
while True:
if camera:
ret, img = camera.read()
else:
raise Exception('Error, camera not setup')
if not ret:
print('no image from camera')
time.sleep(1)
continue
ret, jpg = cv2.imencode('.jpg', img)
self.end_headers()
self.wfile.write('--mjpegstream')
self.end_headers()
self.send_header('Content-type', 'image/jpeg')
self.send_header('Content-length', str(jpg.size))
self.end_headers()
self.wfile.write(jpg.tostring())
def main():
try:
setUpCameraCV()
mjpgServer.ip = 0.0.0.0
mjpgServer.hostname = Socket.gethostname()
server = HTTPServer((ipv4, args['port']), mjpgServer)
print("server started on {}:{}".format(Socket.gethostname(), args['port']))
server.serve_forever()
except KeyboardInterrupt:
print('KeyboardInterrupt')
server.socket.close()
if __name__ == '__main__':
main()
另一个问题,如何在客户端(接收器)获取每个帧的时间戳?
![enter image description here](https://i.stack.imgur.com/LwNjc.png)
使用线程处理 I/O 密集型操作(例如从网络摄像头读取帧)是一种经典的编程模型。由于使用访问网络摄像头/相机cv2.VideoCapture().read()
是一个阻塞操作,我们的主程序会停止,直到从相机设备读取帧并返回到我们的脚本。本质上,这个想法是产生另一个线程来处理抓取帧parallel而不是依赖单个线程(我们的“主”线程)来抓取帧顺序的命令。这将允许从 I/O 线程连续读取帧,同时我们的根线程处理当前帧。一旦根线程完成处理其帧,它只需从 I/O 线程获取当前帧,而不必等待阻塞 I/O 操作。
因此,我们可以通过创建一个新线程来提高性能,该新线程除了轮询新帧外什么都不做,而我们的主线程则负责处理当前帧。对于处理多个摄像头流的实现,请查看使用 OpenCV 捕获多个相机流
from threading import Thread
import cv2, time
class VideoStreamWidget(object):
def __init__(self, src=0):
self.capture = cv2.VideoCapture(src)
# Start the thread to read frames from the video stream
self.thread = Thread(target=self.update, args=())
self.thread.daemon = True
self.thread.start()
def update(self):
# Read the next frame from the stream in a different thread
while True:
if self.capture.isOpened():
(self.status, self.frame) = self.capture.read()
time.sleep(.01)
def show_frame(self):
# Display frames in main program
cv2.imshow('frame', self.frame)
key = cv2.waitKey(1)
if key == ord('q'):
self.capture.release()
cv2.destroyAllWindows()
exit(1)
if __name__ == '__main__':
video_stream_widget = VideoStreamWidget()
while True:
try:
video_stream_widget.show_frame()
except AttributeError:
pass
相关相机/IP/RTSP、FPS、视频、线程和多处理帖子
-
Python OpenCV 从相机流式传输 - 多线程、时间戳
-
使用 OpenCV cv2.VideoCapture 在 Python 中从 IP 摄像机进行视频流传输
-
如何使用 OpenCV 捕获多个摄像机流?
-
OpenCV 实时流视频采集速度很慢。如何丢帧或者实时同步?
-
使用 OpenCV VideoWriter 将 RTSP 流存储为视频文件
-
OpenCV 视频保存
-
Python OpenCV 多处理 cv2.VideoCapture mp4
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)