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 buffer
thread 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 original
This is the code that I have written so far.
import torch
from utils import get_device, get_model, plot_square, plot_image, annotate_square_corners, show_box, show_mask, show_points
import numpy as np
from matplotlib import pyplot as plt
from fastsam import FastSAM, FastSAMPrompt
from utils import get_box_coordinates, get_image_with_box_corners
import cv2
import threading
import time
# Configuration
fast_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 = 1
model = 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 frames
frame_buffer = []
# Flag to control thread execution
running = True
# Desired frame rate
FRAME_RATE = 32
# Set the frame rate of the capture object
cap.set(cv2.CAP_PROP_FPS, FRAME_RATE)
# Function to continuously capture frames and buffer them for one second
def 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 buffer
def 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 image
def 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 thread
capture_thread = threading.Thread(target=capture_frames)
capture_thread.daemon = True
capture_thread.start()
# Start process frames thread
process_thread = threading.Thread(target=process_frames)
process_thread.daemon = True
process_thread.start()
# Wait for threads to finish
capture_thread.join()
process_thread.join()
# Release the capture object and close the window
cap.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!