如何在 raspberry pi 中的多线程中使用 opencv "detectMultiScale()" 函数

how to use opencv "detectMultiScale()" function in multithreading in raspberry pi

OpenCV python 的 detectMultiScale() 函数在 raspberry pi 的多线程场景中使用时停止响应 3.

我希望制作两个线程;一个用于显示实时图像,另一个用于检测物体并找到其中心。即使实时图像显示功能运行顺利,其 detectMultiScale() 功能也没有显示任何响应。我做了一些在线研究,发现 OpenCV 不能很好地处理并行处理。

import threading
import cv2
import numpy as np
from picamera.array import PiRGBArray
from picamera import PiCamera
import time
global image, center
center=[]
def capture():
    global image, center
    cv2.namedWindow('image',cv2.WINDOW_NORMAL)
    cv2.moveWindow('image',0,0)
    cv2.resizeWindow('image', 800,608)
    camera=PiCamera()
    camera.resolution=(800,608)
    camera.framerate=50
    rawCapture=PiRGBArray(camera,size=(800,608))
    for frame in camera.capture_continuous(rawCapture,format='bgr',use_video_port=True):
        image=frame.array      
        cv2.imshow('image',image)

        key=cv2.waitKey(1)& 0xFF
        rawCapture.truncate(0)
        if key==ord('q'):
            break    
    cv2.destroyAllWindows()

def detect():
    global image, center
    time.sleep(2)
    drop_cascade = cv2.CascadeClassifier('cascade.xml')
    while True:
        faces = drop_cascade.detectMultiScale(image, 1.25, 7)
        for (x, y, w, h) in faces:
            center.append([x,y,w,h])

if __name__ == '__main__':
    thread1=threading.Thread(target=capture)
    thread2=threading.Thread(target=detect)
    thread1.start()
    thread2.start()

问题是 Threads 固有的,它是由全局解释器锁引起的。线程共享程序内存。为了防止由不同线程更改同一变量引起的冲突,Python 将执行锁定到特定线程。这意味着在任何时候都只有一个线程 运行s。当 CPU 空闲时,程序在线程之间切换,使 IO-bound 应用程序 运行 更快。

要同时完成 CPU 繁重的任务,您必须使用 multiprocessing。在单独的 CPU 核心上同时处理 运行 并且不共享内存。

Here 是关于全局解释器锁的优秀且冗长的解释。

编辑:

Here 是关于多处理的信息。

将线程与异步多处理进行比较的示例代码:

    import time
    import threading
    from  multiprocessing import Pool

    # cpu heavy functions
    def doTask(val):
            for i in range(10000000):
                    x = i*i
            print(str.format('Task {} done!',val))

    def doOtherTask(val):
            for i in range(10000000):
                    x = i*i
            print(str.format('Other Task {} done!',val))

    if __name__ == '__main__':
            print('Threads:')
            # note starttime        
            starttime = time.time()
            # create and run threads
            thread1 = threading.Thread(doTask(1))
            thread2 = threading.Thread(doTask(2))
            thread3 = threading.Thread(doOtherTask(1))
            thread4 = threading.Thread(doOtherTask(2))
            thread1.start()
            thread2.start()
            thread3.start()
            thread4.start()

            print(str.format('Threads took {} seconds', time.time()-starttime))

            print('Multiprocessing:')
            #reset starttime
            starttime = time.time()
            # create and run processes
            arguments = [1,2]
            p = Pool()
            p.map_async(doTask,arguments)
            p.map_async(doOtherTask,arguments)
            # close and join pool, so program execution waits 
            # for all tasks to finish
            p.close()
            p.join()

            print(str.format('Multiprocessing took {} seconds', time.time()-starttime))