简体   繁体   中英

Python OpenCV multiprocessing works on MacOS and Windows but not Ubuntu

The following code runs well on python 3.8 on MacOS Big Sur and Windows 10: quits with 'q' and can be re-run many times.

But on Ubuntu 20.04, it does not release webcam resource on 'q' and subsequent runs returns VIDIOC_QBUF: No buffer space available . The system needs to be hard rebooted to fix this.

If I comment out the line cam_process.terminate() , then code does not exit on 'q' until CTRL-C is pressed.

How should I:

  1. Correct the code with cam_process.terminate() to release webcam resource on Ubuntu?
  2. Correct the code to quit properly without cam_process.terminate() ?

Any technical insights into the why is most appreciated.

Edit: fix f-strings typo errors.

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()

Ok, after working on this for the last 2 hours, I finally got my own answer for 2, to quit properly without cam_process.terminate() .

The code could not quit properly (hung) because the cam_image_queue was not empty. It contained the last frame put by the cam_loop . After I flushed the cam_image_queue , the program quit gracefully as expected and released the webcam resource properly. It seems Ubuntu is more particular about flushing the queue than MacOS or Windows.

To answer 1: do not call cam_process.terminate() as it kills the process without releasing resources properly.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM