Python 使用opencv捕获视频时并行运行进程

Python 使用opencv捕获视频时并行运行进程,python,multithreading,opencv,Python,Multithreading,Opencv,我正在使用opencv从我的网络摄像头捕获视频。每5秒钟,我处理一帧/一幅图像,这可能需要几秒钟的时间。到目前为止一切正常。但无论何时处理一帧,整个视频都会冻结几秒钟(直到处理完成)。我正试图通过使用线程来摆脱它。以下是我迄今为止所做的: 在捕获视频的while循环内: while True: ret, image = cap.read() if next_time <= datetime.now(): content_t

我正在使用opencv从我的网络摄像头捕获视频。每5秒钟,我处理一帧/一幅图像,这可能需要几秒钟的时间。到目前为止一切正常。但无论何时处理一帧,整个视频都会冻结几秒钟(直到处理完成)。我正试图通过使用线程来摆脱它。以下是我迄今为止所做的:

在捕获视频的while循环内:

    while True:
        ret, image = cap.read()

        if next_time <= datetime.now():

            content_type = 'image/jpeg'
            headers = {'content-type': content_type}
            _, img_encoded = cv2.imencode('.jpg', image)

            loop = asyncio.get_event_loop()
            future = asyncio.ensure_future(self.async_faces(img_encoded, headers))
            loop.run_until_complete(future)

            next_time += period
            ...

        cv2.imshow('img', image)
但不幸的是,它不起作用

编辑1

在下面我添加了整个事情应该做的事情

最初,该函数看起来像:

import requests
import cv2
from datetime import datetime, timedelta

def face_recognition(self):

    # Start camera
    cap = cv2.VideoCapture(0)

    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

    emotional_states = []
    font = cv2.FONT_HERSHEY_SIMPLEX

    period = timedelta(seconds=self.time_period)
    next_time = datetime.now() + period

    cv2.namedWindow('img', cv2.WND_PROP_FULLSCREEN)
    cv2.setWindowProperty('img', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

    while True:
        ret, image = cap.read()

        if next_time <= datetime.now():

            # Prepare headers for http request
            content_type = 'image/jpeg'
            headers = {'content-type': content_type}
            _, img_encoded = cv2.imencode('.jpg', image)

            try:
                # Send http request with image and receive response
                response = requests.post(self.url, data=img_encoded.tostring(), headers=headers)
                emotional_states = response.json().get("emotions")
                face_locations = response.json().get("locations")
            except Exception as e:
                emotional_states = []
                face_locations = []
                print(e)

            next_time += period

        for i in range(0, len(emotional_states)):
            emotion = emotional_states[i]
            face_location = face_locations[i]
            cv2.putText(image, emotion, (int(face_location[0]), int(face_location[1])),
                        font, 0.8, (0, 255, 0), 2, cv2.LINE_AA)

        cv2.imshow('img', image)
        k = cv2.waitKey(1) & 0xff
        if k == 27:
            cv2.destroyAllWindows()
            cap.release()
            break
        if k == ord('a'):
            cv2.resizeWindow('img', 700,700)

python中的线程有点奇怪。如果通过
ThreadPoolExecutor
生成线程,则这些线程将在同一进程中执行。您仍然受到全局解释器锁的限制。在python中使用线程只有在IO瓶颈和CPU空闲等待IO时才有意义。这很可能就是程序在处理映像时挂起的原因(您是CPU瓶颈,而不是IO瓶颈)。有一个
ProcessPoolExecutor
可以生成不同的进程,但是我担心这可能不适用于asyncio事件循环。感谢您的澄清。不幸的是,我没有其他想法。我的脑袋告诉我,事情不会那么复杂。但很明显,我对这东西也不是很有经验。能否通过运行一个单独的python进程来分离进程,该进程在文件系统的某个文件夹中查找图像?第一个进程定期将图像写入该文件夹?这样一来,当第二个进程占用大量CPU时,第一个进程就不应该被锁定,不利的一面可能是IO操作会导致性能下降。我忽略了这里的大局。为什么要对图像进行JPEG编码?你要把它送到哪里?没有
waitKey()
,如何运行
imshow()
?您运行的是什么机器和操作系统?为什么要删除所有的
import
语句,这样其他人就不能运行它了?整件事该怎么办?可能是重复的。线程可以通过减少I/O延迟来提高性能,并且仅在程序等待新帧时才起作用。
import requests
import cv2
from datetime import datetime, timedelta

def face_recognition(self):

    # Start camera
    cap = cv2.VideoCapture(0)

    cap.set(cv2.CAP_PROP_FRAME_WIDTH, 1920)
    cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 1080)

    emotional_states = []
    font = cv2.FONT_HERSHEY_SIMPLEX

    period = timedelta(seconds=self.time_period)
    next_time = datetime.now() + period

    cv2.namedWindow('img', cv2.WND_PROP_FULLSCREEN)
    cv2.setWindowProperty('img', cv2.WND_PROP_FULLSCREEN, cv2.WINDOW_FULLSCREEN)

    while True:
        ret, image = cap.read()

        if next_time <= datetime.now():

            # Prepare headers for http request
            content_type = 'image/jpeg'
            headers = {'content-type': content_type}
            _, img_encoded = cv2.imencode('.jpg', image)

            try:
                # Send http request with image and receive response
                response = requests.post(self.url, data=img_encoded.tostring(), headers=headers)
                emotional_states = response.json().get("emotions")
                face_locations = response.json().get("locations")
            except Exception as e:
                emotional_states = []
                face_locations = []
                print(e)

            next_time += period

        for i in range(0, len(emotional_states)):
            emotion = emotional_states[i]
            face_location = face_locations[i]
            cv2.putText(image, emotion, (int(face_location[0]), int(face_location[1])),
                        font, 0.8, (0, 255, 0), 2, cv2.LINE_AA)

        cv2.imshow('img', image)
        k = cv2.waitKey(1) & 0xff
        if k == 27:
            cv2.destroyAllWindows()
            cap.release()
            break
        if k == ord('a'):
            cv2.resizeWindow('img', 700,700)
from flask import Flask, request, Response
import numpy as np
import cv2
import json

@app.route('/api', methods=['POST'])
def facial_emotion_recognition():

    # Convert string of image data to uint8
    nparr = np.fromstring(request.data, np.uint8)
    # Decode image
    img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)

    # Analyse the image
    emotional_state, face_locations = emotionDetection.analyze_facial_emotions(img)

    json_dump = json.dumps({'emotions': emotional_state, 'locations': face_locations}, cls=NumpyEncoder)

    return Response(json_dump, mimetype='application/json')