摄像头提供的Python OpenCV流-多线程,时间戳 [英] Python OpenCV streaming from camera - multithreading, timestamps

查看:779
本文介绍了摄像头提供的Python OpenCV流-多线程,时间戳的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在RasbpberryPI 3上运行了简单的python脚本.该脚本可用于打开视频设备并使用MJPEG将数据流(800x600)流到HTTP端点.当我重新获得此流时,我的rasbpberrypi核心之一可在100%上运行.可以通过多线程运行OpenCV吗?

I ran simple python script on RasbpberryPI 3. This script is resposible to open video device and stream data (800x600) to HTTP endpoint using MJPEG. When I recive this stream one of my rasbpberrypi cores works on 100%. It possible to run OpenCV with multi threading?

这是我的代码

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()

另一个问题,如何在客户端(接收方)获得每个帧的时间戳?

Another question, how to get timestamp of each frame on the client side (receiver) it possible?

推荐答案

使用线程处理I/O繁重的操作(例如从网络摄像头读取帧)是一种经典的编程模型.由于使用cv2.VideoCapture().read()访问网络摄像头/摄像机是一项阻止操作,因此我们的主程序被暂停,直到从摄像机设备读取帧并返回到我们的脚本为止.本质上,这个想法是生成另一个线程来处理 parallel 的帧,而不是依靠单个线程(我们的主"线程)以顺序的顺序来捕获帧.这将允许从I/O线程连续读取帧,而我们的根线程将处理当前帧.根线程完成处理其帧后,仅需要从I/O线程获取当前帧,而不必等待阻塞I/O操作.

Using threading to handle I/O heavy operations (such as reading frames from a webcam) is a classic programming model. Since accessing the webcam/camera using cv2.VideoCapture().read() is a blocking operation, our main program is stalled until the frame is read from the camera device and returned to our script. Essentially the idea is to spawn another thread to handle grabbing the frames in parallel instead of relying on a single thread (our 'main' thread) to grab the frames in sequential order. This will allow frames to be continuously read from the I/O thread, while our root thread processes the current frame. Once the root thread finishes processing its frame, it simply needs to grab the current frame from the I/O thread without having to wait for blocking I/O operations.

因此,我们可以通过创建一个新线程来提高性能,该线程除了轮询新帧外什么都不做,而我们的主线程则负责处理当前帧.有关处理多个摄像机流的实现,请查看捕获多个摄像机OpenCV流

Thus we can improve performance by creating a new thread that does nothing but poll for new frames while our main thread handles processing the current frame. For an implementation to handle multiple camera streams, take a look at capture multiple camera streams with 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

这篇关于摄像头提供的Python OpenCV流-多线程,时间戳的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆