I want to get images from one thread (with 32 Frames per second) and store them in a buffer (a list, or numpy array) then process them in another thread. Then show the final output in another thread. Altogether there should be 3 threads.
thread 1 -> Capture images taken in one second and store them in a bufferthread 2 -> Process 32 images as a batch (A function has been written for processing one image. For the moment let's say "process_image(image)"thread 3 -> Show processed image buffer in another thread. Frame rate should also be the same as the originalThis is the code that I have written so far.
import torchfrom utils import get_device, get_model, plot_square, plot_image, annotate_square_corners, show_box, show_mask, show_pointsimport numpy as npfrom matplotlib import pyplot as pltfrom fastsam import FastSAM, FastSAMPromptfrom utils import get_box_coordinates, get_image_with_box_cornersimport cv2import threadingimport time# Configurationfast_sam_checkpoint = "weights/FastSAM-x.pt"fast_sam_s_checkpoint = "weights/FastSAM-s.pt"# device = get_device()device = "cpu"# ######################################## model_name = input("Enter the model name you want >>> ")model_name = "fastSAM-s"camera_index = 1model = get_model(model_name)# Initialize the video capture object with the index of the webcam (usually 0)cap = cv2.VideoCapture(camera_index)# Buffer for storing framesframe_buffer = []# Flag to control thread executionrunning = True# Desired frame rateFRAME_RATE = 32# Set the frame rate of the capture objectcap.set(cv2.CAP_PROP_FPS, FRAME_RATE)# Function to continuously capture frames and buffer them for one seconddef capture_frames(): global frame_buffer, running while running: start_time = time.time() # Record the start time for each loop iteration ret, frame = cap.read() # Read frame from webcam if not ret: print("Error: Couldn't read frame.") break frame_buffer.append(frame) # Calculate the time taken to capture the frame and sleep accordingly elapsed_time = time.time() - start_time delay = max(1.0 / FRAME_RATE - elapsed_time, 0) time.sleep(delay)# Function to process frames from the bufferdef process_frames(): global frame_buffer, running while running: if frame_buffer: frame = frame_buffer.pop(0) # Get the oldest frame from the buffer try: # Processing frame # print(frame.shape);print(len(frame_buffer)) box_corners_dict = get_box_coordinates(frame, model, device, False, False, False) print(box_corners_dict) # annotated_frame = get_image_with_box_corners(frame, box_corners_dict) # in RGB # Showing image # cv2.imshow("Annotated image", annotated_frame) show_annotated_image(frame) if cv2.waitKey(1) & 0xFF == ord('q'): running = False # Stop the threads if 'q' is pressed break except ValueError: pass# Function to show annotated imagedef show_annotated_image(frame): # Dummy function to show the frame, you can replace this with your actual logic to annotate and display the frame cv2.imshow("Annotated image", frame)# Start capture frames threadcapture_thread = threading.Thread(target=capture_frames)capture_thread.daemon = Truecapture_thread.start()# Start process frames threadprocess_thread = threading.Thread(target=process_frames)process_thread.daemon = Trueprocess_thread.start()# Wait for threads to finishcapture_thread.join()process_thread.join()# Release the capture object and close the windowcap.release()cv2.destroyAllWindows()At the moment this only shows the first 32 frames captured in the first second at a very slow speed. How can I optimize this code for my task?
Thank you in advance for your kind assistance!