Python OpenCV 多处理适用于 MacOS 和 Windows,但不适用于 Ubuntu

Python OpenCV multiprocessing works on MacOS and Windows but not Ubuntu

以下代码 运行 在 MacOS Big Sur 和 Windows 3.8 和 Windows 10 上运行良好 运行:退出 'q' 并且可以重新 运行 很多次。

但是在 Ubuntu 20.04 上,它不会在 'q' 和随后的 运行 returns VIDIOC_QBUF: No buffer space available 上释放网络摄像头资源。系统需要硬重启才能解决这个问题。

如果我注释掉行 cam_process.terminate(),则代码不会在 'q' 上退出,直到按下 CTRL-C

我应该如何:

  1. 使用 cam_process.terminate() 更正代码以在 Ubuntu 上释放网络摄像头资源?
  2. 更正代码以在没有 cam_process.terminate() 的情况下正确退出?

任何关于原因的技术见解都非常感谢。

编辑:修复 f 字符串拼写错误。

import multiprocessing
import cv2

# Notes:
# 0. Tested on python 3.8 on all platforms.
# 1. Code works fine on MacOS and Windows. Can quit and run many times.
# 2. Code does NOT release webcam on Ubuntu, needs hard reboot!
#    Problem caused by line *: cam_process.terminate()
#    Subsequent runs gets VIDIOC_QBUF: No buffer space available error
# 3. If comment out line *, then subprocess does not end, needs CTRL-C to break.

def cam_loop(cam_image_queue, msg_queue):
    cap = cv2.VideoCapture(0)
    while True:
        hello, img = cap.read()
        cam_image_queue.put(img)
        if not msg_queue.empty():
            print("got quit msg")
            break
    print(f"before cap release, isOpened={cap.isOpened()}")
    cap.release()
    print(f"after cap release, isOpened={cap.isOpened()}")

def main():
    cam_image_queue = multiprocessing.Queue()
    msg_queue = multiprocessing.Queue()
    cam_process = multiprocessing.Process(
        target=cam_loop,
        args=(cam_image_queue, msg_queue,),
    )
    print("starting process...")
    cam_process.start()
    while True:
        if cam_image_queue.empty():
            continue
        img = cam_image_queue.get()
        cv2.imshow("from queue", img)
        key = cv2.waitKey(1)
        if key == ord("q"):
            msg_queue.put("quit")
            break
    print("closing process...")
    # using terminate() or close() will hang webcam resource on Ubuntu!
    cam_process.terminate()    # *
    all_done = False
    while not all_done:
        cam_process.join(1)
        if cam_process.exitcode is not None:
            all_done = True
        else:
            print("code=", cam_process.exitcode)
    print("after cam_process join")
    cv2.destroyAllWindows()

if __name__ == "__main__":
    main()

好的,经过最后 2 个小时的努力,我终于得到了自己的答案 2,即在没有 cam_process.terminate() 的情况下正确退出。

代码无法正常退出(挂起),因为 cam_image_queue 不为空。它包含 cam_loop 放置的最后一帧。在我刷新 cam_image_queue 后,程序按预期正常退出并正确释放了网络摄像头资源。似乎 Ubuntu 比 MacOS 或 Windows.

更注重刷新队列

回答 1:不要调用 cam_process.terminate(),因为它会在没有正确释放资源的情况下终止进程。