在 python 中使用带有多线程的 opencv2 时使用率非常高 CPU
Very high CPU usage when using opencv2 with multithreading in python
我正在尝试使用 opencv2 创建自动考勤系统,其中我需要从 IP 摄像机获取 rtsp 流,从中查找人脸并识别人脸。
因为人脸识别功能需要一些时间来识别人脸,所以我从抓帧和画图创建了不同的线程。
但仅创建 2 个线程,一个用于帧读取,另一个用于绘图,就使用了大约 70% CPU。
并创建 pytorch_facenet 模型增加使用率 80-90% CPU.
有谁知道如何减少 CPU 使用量?
我的程序:
import cv2
import threading
from facenet_pytorch import InceptionResnetV1
cap = cv2.VideoCapture("rtsp://test:Test12345@125.0.0.1")
resnet = InceptionResnetV1(pretrained='vggface2').eval()
ret, frame = cap.read()
exit = False
def th1():
global ret, frame, exit
while True:
ret, frame = cap.read()
if exit:
break
def th2():
global ret, frame, exit
while True:
cv2.imshow('frame', frame)
cv2.waitKey(1)
if cv2.getWindowProperty('frame',cv2.WND_PROP_VISIBLE) < 1:
exit = True
break
t1 = threading.Thread(target=th1)
t1.start()
t2 = threading.Thread(target=th2)
t2.start()
更新:
我在除帧读取之外的所有线程中都使用了 time.sleep(0.2)。
它奏效了,我的 cpu 使用率现在是 30%。
此代码有效。
第一个循环(线程)将尝试尽可能快地读取帧。
帧可以每秒更新 100 次或更多,但速度太快了。尝试添加 time.sleep(0.03)
.
并且在第二个循环中,您可以将 waitKey()
参数更改为 30。
import time
def th1():
global ret, frame, exit
while True:
ret, frame = cap.read()
time.sleep(0.03)
if exit:
break
def th2():
global ret, frame, exit
while True:
cv2.imshow('frame', frame)
cv2.waitKey(30)
if cv2.getWindowProperty('frame',cv2.WND_PROP_VISIBLE) < 1:
exit = True
break
两个问题。
th2
在几乎紧密的循环中运行。它不会消耗 CPU 的整个核心,因为 waitKey(1)
会休眠一段时间。
线程之间根本没有同步,但你需要它。您需要 threading.Event
来通知消费者线程有新帧。消费者线程必须等到新帧可用,因为一次又一次地显示同一个旧帧是没有意义的。您可以偷懒并使用 waitKey(30)
代替。对于显示线程,这已经足够了。
VideoCapture
。你根本不做任何错误检查!您必须检查:
cap = cv2.VideoCapture("rtsp://test:Test12345@125.0.0.1")
assert cap.isOpened()
...
和
while True:
ret, frame = cap.read()
if not ret:
break
...
我正在尝试使用 opencv2 创建自动考勤系统,其中我需要从 IP 摄像机获取 rtsp 流,从中查找人脸并识别人脸。
因为人脸识别功能需要一些时间来识别人脸,所以我从抓帧和画图创建了不同的线程。
但仅创建 2 个线程,一个用于帧读取,另一个用于绘图,就使用了大约 70% CPU。 并创建 pytorch_facenet 模型增加使用率 80-90% CPU.
有谁知道如何减少 CPU 使用量?
我的程序:
import cv2
import threading
from facenet_pytorch import InceptionResnetV1
cap = cv2.VideoCapture("rtsp://test:Test12345@125.0.0.1")
resnet = InceptionResnetV1(pretrained='vggface2').eval()
ret, frame = cap.read()
exit = False
def th1():
global ret, frame, exit
while True:
ret, frame = cap.read()
if exit:
break
def th2():
global ret, frame, exit
while True:
cv2.imshow('frame', frame)
cv2.waitKey(1)
if cv2.getWindowProperty('frame',cv2.WND_PROP_VISIBLE) < 1:
exit = True
break
t1 = threading.Thread(target=th1)
t1.start()
t2 = threading.Thread(target=th2)
t2.start()
更新:
我在除帧读取之外的所有线程中都使用了 time.sleep(0.2)。 它奏效了,我的 cpu 使用率现在是 30%。
此代码有效。
第一个循环(线程)将尝试尽可能快地读取帧。 帧可以每秒更新 100 次或更多,但速度太快了。尝试添加
time.sleep(0.03)
.并且在第二个循环中,您可以将
waitKey()
参数更改为 30。import time def th1(): global ret, frame, exit while True: ret, frame = cap.read() time.sleep(0.03) if exit: break def th2(): global ret, frame, exit while True: cv2.imshow('frame', frame) cv2.waitKey(30) if cv2.getWindowProperty('frame',cv2.WND_PROP_VISIBLE) < 1: exit = True break
两个问题。
th2
在几乎紧密的循环中运行。它不会消耗 CPU 的整个核心,因为waitKey(1)
会休眠一段时间。线程之间根本没有同步,但你需要它。您需要
threading.Event
来通知消费者线程有新帧。消费者线程必须等到新帧可用,因为一次又一次地显示同一个旧帧是没有意义的。您可以偷懒并使用waitKey(30)
代替。对于显示线程,这已经足够了。VideoCapture
。你根本不做任何错误检查!您必须检查:
cap = cv2.VideoCapture("rtsp://test:Test12345@125.0.0.1")
assert cap.isOpened()
...
和
while True:
ret, frame = cap.read()
if not ret:
break
...