0

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()
Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Creek
  • 207
  • 2
  • 12
  • 1
    not sure about python, but probably YES. You are running an endless loop which will run and consume processing power, until it reaches a sleep or crashes or similar. – Micka Aug 25 '22 at 10:01
  • You should not dramatically change the topic of a question, because previous comments and answers might not fit anymore afterwards. – Micka Aug 25 '22 at 15:52
  • 1
    Not sure about python, but you should not manipulate an object like the videocapture in a thread while another thread does access it. You can quit your thread by leaving the endless loop, for example by update(self): while self.continueProcessing and set self.continueProcessing to false outside of the thread. But make sure it is an atomic operation. – Micka Aug 25 '22 at 15:55

1 Answers1

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

SystemSigma_
  • 1,059
  • 4
  • 18
  • 1
    Thanks a lot. The answer is very useful and clear. I have a question if I create difference class object the with statement should be `with ThreadedCamera(src1) as camera` and write another line `with ThreadedCamera(src2) as camera` .... etc? – Creek Aug 26 '22 at 02:32
  • 1
    Of course you can do this, you will have access to different cameras in different threads. However, I prefer using threads outside classes, so it's easier to understand the execution flow and make the threads join. – SystemSigma_ Aug 26 '22 at 07:13