簡體   English   中英

Python 中的多線程 cv2.imshow() 不起作用

[英]Multithreaded cv2.imshow() in Python does not work

我有兩個攝像頭(使用 OpenNI,我每個攝像頭有兩個流,由驅動程序 API 的同一個實例處理)並且希望有兩個線程,每個線程獨立地從每個攝像頭捕獲數據,即驅動程序 API 的一個實例,說cam_handler ,我每個相機有兩個流depthrgb ,比如cam_handler.RGB1_streamcam_handler.DEPTH1_stream

這是相同的代碼:

import threading

def capture_and_save(cam_handle, cam_id, dir_to_write, log_writer, rgb_stream,
                     depth_stream, io):
    t = threading.currentThread()
    shot_idx = 0
    rgb_window = 'RGB' + str(cam_id)
    depth_window = 'DEPTH' + str(cam_id)
    while getattr(t, "do_run", True):
        if rgb_stream is not None:

            rgb_array = cam_handle.get_rgb(rgb_stream)
            rgb_array_disp = cv2.cvtColor(rgb_array, cv2.COLOR_BGR2RGB)
            cv2.imshow(rgb_window, rgb_array_disp)
            cam_handle.save_frame('rgb', rgb_array, shot_idx, dir_to_write + str(cam_id + 1))
            io.write_log(log_writer[cam_id], shot_idx, None)

        if depth_stream is not None:
            depth_array = cam_handle.get_depth(depth_stream)
            depth_array_disp = ((depth_array / 10000.) * 255).astype(np.uint8)
            cv2.imshow(depth_window, np.uint8(depth_array_disp))
            cam_handle.save_frame('depth', depth_array, shot_idx, dir_to_write + str(cam_id + 1))
        shot_idx = shot_idx + 1

        key = cv2.waitKey(1)
        if key == 27:  # exit on ESC
            break
    print "Stopping camera %d thread..." % (cam_id + 1)
    return

def main():
    ''' Setup camera threads '''
    cam_threads = []
    dir_to_write = "some/save/path"
    for cam in range(cam_count):
        cam = (cam + 1) % cam_count
        cv2.namedWindow('RGB' + str(cam))
        cv2.namedWindow('DEPTH' + str(cam))
        one_thread = threading.Thread(target=capture_and_save,
                                      name="CamThread" + str(cam + 1),
                                      args=(cam_cap, cam, dir_to_write,
                                            log_writer,
                                            rgb_stream[cam], depth_stream[cam], io,))
        cam_threads.append(one_thread)
        one_thread.daemon = True
        one_thread.start()

        try:
            while True:
                pass
                # cv2.waitKey(1)
        except KeyboardInterrupt:
            ''' Stop everything '''
            for each_thread in cam_threads:
                each_thread.do_run = False
                each_thread.join(1)
            cam_cap.stop_rgb(rgb_stream)
            cam_cap.stop_depth(depth_stream)

            ''' Stop and quit '''
            openni2.unload()
            cv2.destroyAllWindows()

if __name__ == '__main__':
    main()      

所以,我的問題是,如果我從代碼中刪除cv2.imshow()行,一切都會按預期運行,並且我會將兩個相機輸出保存到文件中。 但是,使用cv2.imshow() ,只創建了“空白” windows 並且線程似乎“卡住”了,根本沒有 output。
我嘗試了幾個建議,包括將namedWindow創建移動到主線程以及capture_and_save線程。 我也嘗試過在waitKey()周圍移動,因為據說 OpenCV 只允許在主線程中使用waitKey() 然而,沒有區別。

我通過使用mutables,將字典cam_disp = {}傳遞給線程並讀取主線程中的值來解決了這個問題。 cv2.imshow()在主線程中保存效果最佳,因此效果很好。 我不確定這是否是“正確”的方式,所以歡迎所有建議。

嘗試在線程目標capture_and_save移動cv2.namedWindow('RGB' + str(cam))

cv2.imshow函數不是線程安全的。 只是移動cv2.namedWindowthreading.Thread的呼叫cv2.imshow

import cv2
import threading

def run():
    cap = cv2.VideoCapture('test.mp4')
    cv2.namedWindow("preview", cv2.WINDOW_NORMAL)
    while True:
        ret, frame = cap.read()
        if frame is None:
            print("Video is over")
            break
        cv2.imshow('preview', frame)
        cv2.waitKey(1)
    cap.release()
    cv2.destroyAllWindows()

if __name__ == "__main__":
    thread = threading.Thread(target=run)
    thread.start()
    thread.join()
    print("Bye :)")

我認為,不知道:) 但這是我最好的解釋。

當您嘗試在視圖中打開圖像時,您會將圖像從相機線程傳遞到 GUI 線程。 這樣做時,您將不同步。 有時它會起作用。 我認為你會/可能會在某個時候遇到同樣的問題。 (我做過)運行超過 1 個線程時會更明顯。 您可以做的是使用線程安全的 memory(隊列)或線程鎖。

然后,您將線程鎖放在相機保存周圍,在線程中,並在 main 中讀取 imshow ,您將是安全的。 還有 GIL 令人毛骨悚然,您還需要了解更多信息。 但最簡單的是你的情況下的線程鎖,但這一切都取決於你需要多少控制數據流和“讀取相機”的優先級或“實時”在屏幕上顯示。 @DarkSidds 的回答也是正確的。 但是,如果您有超過 1 個攝像頭並且這些攝像頭是從線程中寫入的,那么您將崩潰。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM