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