在 Python 多处理进程中运行较慢的 OpenCV 代码片段

Posted

技术标签:

【中文标题】在 Python 多处理进程中运行较慢的 OpenCV 代码片段【英文标题】:OpenCV code snippet running slower inside Python multiprocessing process 【发布时间】:2021-01-30 13:59:33 【问题描述】:

我正在使用多处理进行一些测试以并行化人脸检测和识别,我遇到了一个奇怪的行为,其中 detectMultiScale()(执行人脸检测)在子进程中的运行速度比在父进程中慢(只是调用函数)。

因此,我编写了下面的代码,其中将 10 个图像排入队列,然后使用以下两种方法之一顺序执行人脸检测:仅调用检测函数或在单​​个新进程中运行它。对于每个 detectMultiScale() 调用,都会打印执行时间。执行此代码在第一种方法中平均每次调用为 0.22 秒,在第二种方法中为 0.54 秒。此外,第二种方法处理 10 张图像的总时间也更长。

我不知道为什么相同的代码 sn-p 在新进程中运行速度较慢。如果总时间更长我会理解(考虑到设置新进程的开销),但我不明白。作为记录,我在 Raspberry Pi 3B+ 中运行它。

import cv2
import multiprocessing
from time import time, sleep

def detect(face_cascade, img_queue, bnd_queue):
    while True:
        image = img_queue.get()
        if image is not None:
            gray_image = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
            ti = time()
            ########################################
            faces = face_cascade.detectMultiScale(
                                gray_image,
                                scaleFactor=1.1,
                                minNeighbors=3,
                                minSize=(130, 130))
            ########################################
            tf = time()
            print('det time: ' + str(tf-ti))
                            
            if len(faces) > 0:
                max_bounds = (0,0,0,0)
                max_size = 0
                for (x,y,w,h) in faces:
                     if w*h > max_size:
                         max_size = w*h
                         max_bounds = (x,y,w,h)
            img_queue.task_done()
            bnd_queue.put('bound')
        else:
            img_queue.task_done()
            break


face_cascade = cv2.CascadeClassifier('../lbpcascade_frontalface_improved.xml')
cam = cv2.VideoCapture(0)
cam.set(cv2.CAP_PROP_FRAME_WIDTH, 2592)
cam.set(cv2.CAP_PROP_FRAME_HEIGHT, 1944)
cam.set(cv2.CAP_PROP_BUFFERSIZE, 1)

img_queue = multiprocessing.JoinableQueue()

i = 0
while i < 10:
    is_there_frame, image = cam.read()
    if is_there_frame:
        image = image[0:1944, 864:1728]
        image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
        img_queue.put(image)
        i += 1

bnd_queue = multiprocessing.JoinableQueue()
num_process = 1

ti = time()
# MULTIPROCESSING PROCESS APPROACH
for _ in range(num_process):
    p = multiprocessing.Process(target=detect, args=(face_cascade, img_queue, bnd_queue))
    p.start()

for _ in range(num_process):
    img_queue.put(None)
#     
# FUNCTION CALL APPROACH
#img_queue.put(None)
#while not img_queue.empty():
#    detect(face_cascade, img_queue, bnd_queue)

img_queue.join()
tf = time()

print('TOTAL TIME: ' + str(tf-ti))

while not bnd_queue.empty():
    bound = bnd_queue.get()
    if bound != 'bound':
        print('ERROR')
    bnd_queue.task_done()

【问题讨论】:

【参考方案1】:

我遇到了同样的问题,我认为原因是任务在某种程度上受 I/O 限制,而且多处理本身也产生了开销。 你也可以在这里阅读文章https://www.pyimagesearch.com/2019/09/09/multiprocessing-with-opencv-and-python/ 你用 detectMultiScale() 方法特别提到的问题和我的一样。我也尝试过使用序列化并使变量成为全局变量以及类级别的变量,但没有任何帮助..

【讨论】:

以上是关于在 Python 多处理进程中运行较慢的 OpenCV 代码片段的主要内容,如果未能解决你的问题,请参考以下文章

C# 程序在较慢的 PC 上运行得更快,反之亦然

Talend 作业以较慢的传输速率运行

php-fpm中启用慢日志配置(用于检测执行较慢的PHP脚本)

Python多处理:在父进程退出后运行进程

PHP性能调优---php-fpm中启用慢日志配置(用于检测执行较慢的PHP脚本)

如何使用多处理在Python中运行多个异步进程?