Search code examples
pythonmultithreadingopencvflaskpython-multithreading

Does the thread can terminate when call OpenCV release() method?


The ThreadedCamera Class that get frame from thread.

I have two questions.

Q1: Will it affect program performance if I don't close threads when I create a lot of ThreadedCamera classes?

Q2: Does the thread can terminate when call __del__ method?

from threading import Thread
import cv2, time

class ThreadedCamera(object):
    def __init__(self, src=0):
        self.capture = cv2.VideoCapture(src)
        
        # Start frame retrieval thread
        self.thread = Thread(target=self.update, args=())
        self.thread.daemon = True
        self.thread.start()
        
    def update(self):
        while True:
            if self.capture.isOpened():
                (self.status, self.frame) = self.capture.read()
            
    def get_frame(self):
        return self.frame
    
    def __del__(self): # Q2: Does the self.thread can terminate when call this method ? 
        self.capture.release()

Solution

    1. It is always a good idea to cleanup resources and joining threads. However, since the camera thread is deamon, it will be closed when the calling thread terminates. A more traditional way is to use a threading.Event to trigger the while loop breaking and thread termination.
    2. Why not simply create a graceful shutdown method where everything is cleaned up when you want to? I don't really like playing with core dunder methods like __del__.
    import cv2
    import threading 
    import time
    
    class ThreadedCamera:
        
        def __init__(self, src=0):
            self.capture = cv2.VideoCapture(src)
            self.terminate_camera_thread = threading.Event()
            self.thread = threading.Thread(target=self.update, daemon=True)
            self.thread.start()
        
        def update(self):
            while not self.terminate_camera_thread.is_set():
                if self.capture.isOpened():
                   (self.status, self.frame) = self.capture.read()
    
        def shutdown(self):
            self.terminate_camera_thread.set()
            self.capture.release()
    

    You can automate this cleaning with context managers so you can use with:

    
    with ThreadedCamera() as camera:
    
        # camera processing for loop
    
    

    by adding

    def __enter__(self):
        return self
    
    def __exit__(self, *args, **kwargs):
        self.shutdown()