1
votes

I am converting numpy arrays (webcamera footage loaded with OpenCV) into Tkinter PhotoImage objects to display them on Tkinter GUI. However, the function PIL.ImageTk.PhotoImage() experiences around 800 ms peaks that result in serious drops in frame rate. Here's the snippet:

ar = Image.fromarray(frame)
itk = ImageTk.PhotoImage(ar) # *
lbl = Label()
lbl.configure(image=itk)
lbl.image = itk

I have measured the execution time of the row marked with *:

Number of runs: 72
Total duration: 11.97 seconds
Longest run: 967.05 milliseconds
Shortest run: 1.03 milliseconds
Average run: 166.25 milliseconds
Median run: 1.2 milliseconds
Standard deviation: 315.63 milliseconds

Additionally, here's a plot of the performance: ImageTk.PhotoImage() performance

The pixel count of the image is always the same and I cannot generate conditions where the performance would be consistently low.

Any ideas on how to prevent the spikes? It's not a problem to skip frames if it can be predicted.

PIL version 4.0.0 OpenCV version 3.0.0 Numpy version 1.12.0 Python version: 2.7.12

1

1 Answers

0
votes

Whereas I did not find out the reason or fix to this, I found a workaround that allowed me to have reasonable performance without constant freezes. This solution has two parts:

1) Every captured frame is transfromed into ImageTk.PhotoImage object as before. However, I also measured the duration of this operation. If it took more than 100 ms, the frame was not updated in the GUI.

2) When a frame is captured, a new thread is started to update the GUI image. This allows newly captured frames to be updated even when the problematic long delays are faced. These delayed images will not be shown on GUI leading to some missing frames, which will be quickly replaced by the next frame. This works because the conversion is most of the time very quick.