I created a Tkinter program that displays images processed with OpenCV. The Tkinter GUI has buttons for selecting a folder, viewing the next image, and viewing the previous image, and a canvas showing these images. And when a person checks what type of image this image is using a radio button, the record is saved.
Here's what it looks like for users:
During the 1 second that 5's human makes the decision, I want to start processing and preparing the next image of 3, and then display it immediately when I press the button. I think that will dramatically improve the user experience.
How can I make it? I would appreciate it if you could tell me at least a keyword about what technologies I should look into.
I modified the program based on Ahmed AEK's answer. It worked well and obviously improved the user experience quite a bit by preparing the next image in advance. However, the canvas.draw() part, which draws a pre-prepared image in Tkinter, takes up time on its own. So I couldn't go far in improving it to a level where there is absolutely no delay. This is my fault for not thoroughly analyzing the time for each step in advance.
I couldn't try Redis because there was an initial entry barrier. Thank you both for your excellent answers.
you should be using multithreading, ie: by pushing work to other thread, so that the main thread will not be blocked, the most reliable way is using a Threadpool as follows.
from multiprocessing.pool import ThreadPool
class ImageRepository:
def __init__(self):
self.next_image_future = None
self.threadpool = ThreadPool(1) # 1 worker, we don't need more
def start_image_processing(self):
# initialize and start the first task
self.next_image_future = self.threadpool.apply_async(self.load_next_image)
def get_next_image(self):
if self.next_image_future is not None:
# get the image
new_image = self.next_image_future.get()
# submit task for the next one in future
self.next_image_future = \
self.threadpool.apply_async(self.load_next_image)
return new_image
def load_next_image(self):
print("loading and processing image")
return 5 # new image object
repo = ImageRepository()
repo.start_image_processing() # start grabbing the first image
# get next image and initiate work for the one after it
new_image = repo.get_next_image()
and so every time you get an image, you will be assigning a task to another thread to load and process the next one.