Updating a Picture every frame with data from another process

Hello,

I am trying to use GTK with the OpenCV library. I am getting and processing webcam input with OpenCV in a process separate from the GUI and GTK process. I want to display this processed frame in the GUI with GTK. My current method involves running the CV in a separate process, saving that image to a file, then reading that file on the GUI process and updating a Picture widget frequently using the read file. However, the UI begins to flicker if I try to update the GUI too quickly. Is there another method I should follow if I want to update a Picture frequently, perhaps every frame? Do I still need to save the image to a file, or could I use something like shared memory between the two programs?

I assume that you use gtkmm, as you’ve used the cplusplus tag.

Gio::Subprocess might be useful. It uses pipes to communicate between two programs.

Thanks for pointing me to the link. I think it’ll work better than what I’m currently using for IPC right now.

What about for polling for image data and then updating the image? Should I use the main event loop system?

Hi @baconerie,

You could add a rick callback to the video widget. This way the image is updated only one time for each refresh (vsync). You should also detect if the video data hasn’t changed between consecutive tick callbacks to avoid needless work.

This will adapt the refresh rate of the webcam to the monitor’s refresh rate. For optimal quality one could implement frame interpolation, but that’s overkill most of the times, especially for webcam input!

GtkWidget *video_widget;
guint      video_frame_callback_id;

/* This function is called by GTK on each refresh interval.
 * We detect if the video image has changed and trigger a
 * repaint
 */
static gboolean
video_frame_callback (GtkWidget* widget,
                      GdkFrameClock* frame_clock,
                      gpointer user_data)
{
  bool changed = false;

  /* detect if the video image has changed */

  if (changed)
    {
      // Could also use gtk_image_set_from_file here
      // instead of gtk_widget_queue_draw.
      gtk_widget_queue_draw (video_widget);
    }
}

static void
video_play (void)
{
  if (video_frame_callback_id == 0)
    {
      video_frame_callback_id = gtk_widget_add_tick_callback (video_widget,
                                                              video_frame_callback,
                                                              NULL,
                                                              NULL);
    }
}

static void
video_stop (void)
{
  if (video_frame_callback_id != 0)
    {
      gtk_widget_remove_tick_callback (video_widget, video_frame_callback_id);
      video_frame_callback_id = 0;
    }
}
1 Like

If your program is a C++ program, you can use std::thread to create extra threads.
The gtkmm tutorial has a chapter on Multi-threaded programs.
Gtk and gtkmm are not thread-safe. All GUI handling must occur in the main thread.
IPC with Gio::Subprocess can probably occur in a different thread.

1 Like

Hi,
Instead of creating and reading an image file, it should be possible create a texture from the OpenCV data with Gdk.MemoryTexture.new that you can paint on the next Gtk.Widget.snapshot call.

1 Like