Doug Miller
Doug Miller

Reputation: 1037

How to terminate "multiprocessing.Process" correctly when using "cv2.VideoCapture" (Python OpenCV)?

I'm at a loss for what is happening here. I'm trying to run an opencv VideoCapture process to read frames and put on a Queue for workers to process.

The application never finishes running because the CameraProcess instance never seems to terminate. After a little investigation, it looks like the camera is reported as closed after a call to #release(), but is considered open on the main process.

Should I not be creating a VideoCapture instance from within the Process?

Sample Application:

import cv2
from multiprocessing import Process, Event
from time import sleep

class CameraProcess(Process):
    def __init__(self, camera_id, *args, **kwargs):
        super(CameraProcess, self).__init__(*args, **kwargs)
        self.shutdown = Event()

        self.camera = cv2.VideoCapture(camera_id)
        sleep(1)
        print('Camera is opened? {}'.format(self.camera.isOpened()))

    def run(self):
        while not self.shutdown.wait(0.05):
            print('Doing camera stuff')
            sleep(1)

        self.camera.release()
        print('Camera is closed? {}'.format(not self.camera.isOpened()))

try:
    camera = CameraProcess(0)
    camera.start()
    sleep(5)
    camera.shutdown.set()
    sleep(2)
    print('Camera is closed? {}'.format(not camera.camera.isOpened()))
except KeyboardInterrupt:
    pass
finally:
    camera.terminate()

Application Output:

Camera is opened? True
Doing camera stuff
Doing camera stuff
Doing camera stuff
Doing camera stuff
Doing camera stuff
Camera is closed? True
Camera is closed? False

Environment:

Upvotes: 1

Views: 1241

Answers (1)

Kinght 金
Kinght 金

Reputation: 18341

Strangely, it should be released. But the camera resource is still being occupied. May be it's a bug? Or maybe it's something new to new ...


To release the resource correctly, I define a new method as follow. Then it works.

import cv2
from multiprocessing import Process, Event
from time import sleep

class CameraProcess(Process):
    def __init__(self, camera_id, *args, **kwargs):
        super(CameraProcess, self).__init__(*args, **kwargs)
        self.shutdown = Event()

        self.camera = cv2.VideoCapture(camera_id)
        print('Camera is opened? {}'.format(self.camera.isOpened()))

    def run(self):
        while not self.shutdown.wait(0.05):
            print('Doing camera stuff')
            sleep(1)
        self.camera.release()
        print('[run   ] Camera is closed? {}'.format(not self.camera.isOpened()))

    ## Defind a new method to release the resourse(again).
    def shutup(self):
        self.shutdown.set()
        if self.camera.isOpened():
            self.camera.release()
        print('[shutup] Camera is closed? {}'.format(not self.camera.isOpened()))

try:
    camera = CameraProcess(0)
    camera.start()
    sleep(5)
    camera.shutup()
    sleep(2)
    print('[main  ] Camera is closed? {}'.format(not camera.camera.isOpened()))
except KeyboardInterrupt:
    pass
finally:
    camera.terminate()

The result is OK now.

Camera is opened? True
Doing camera stuff
Doing camera stuff
Doing camera stuff
Doing camera stuff
Doing camera stuff
[shutup] Camera is closed? True
[run   ] Camera is closed? True
[main  ] Camera is closed? True

Upvotes: 3

Related Questions