I’m attempting to display a webcam feed from a USB camera using OpenCV in a Picture widget using GTK 4 / PyGobject. I have a thread populating a queue of OpenCV images (Numpy NDArrays) that have been converted from BGR to RGB. A timeout triggers a callback that retrieves the image from the queue and is supposed to display it but the Picture widget just shows up as a black square.
I’ve verified that the camera capture thread populates the queue correctly and the parent thread can save them as PNGs as expected. I’ve tried this on both MacOS and Ubuntu without success.
GdkPixbuf.Pixbuf.new_from_data() doesn’t copy (or even ref) the data passed as argument. It could be that numpy.array(self._current_frame).ravel() must be kept alive in some way (not sure if it produces new data or just a view into an existing buffer). What happens if you write:
So, it looks like the problem is related to framerate which I was not expecting. While trying to save the Pixbuff object as a PNG to investigate, the application started hanging. I figured the disk write was slow so I lowered the display rate of the camera. When I lower the framerate to 1 FPS it seems to display the image as expected.
I don’t really understand why that would be the case. The only thing I can think of is some kind of race condition between the capture process and the display process.
I suggest using Gtk.Widget.add_tick_callback() to add callback that is called by GTK once per frame (from the GTK rendering engine). Use such callback to pull the latest frame, convert it to a GdkPixbuf and set the paintable.