AuKras
AuKras

Reputation: 1

Incompatibility issues between OpenCV and GTK+ 3

I am developing a real-time screen-capturing program using Python 3.10.4 with OpenCV and GTK+ 3. I ran into an issue I cannot solve - GTK+ 3 seems to be incompatible with OpenCV. To give a bit more context to my problem, I am using GTK+ 3 to capture each frame from any selected window (minimized or not) using GdkPixbuf and I am using OpenCV to efficiently process and show each captured frame in real-time.

Here's the issue. Consider the following simple example:

import numpy as np
import cv2
import gi

gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

img = np.zeros((100,100,3))
cv2.imshow('test', img) # ERROR happens here
cv2.waitKey(0)

The following code produces a segmentation fault (SIGSEGV) (exit code 139, signal 11). The segmentation fault happens exactly when cv2.imshow() is called. If, however, I were to change GTK version to 2, by writting gi.require_version("Gtk", "2.0") or remove it altogether, the SIGSEGV does not occur. This is not a solution, since I need GTK+ 3 at the very least.

So far, I tried downgrading OpenCV, but no other version worked. What I found to be working is PyGTK in place of GTK+ 3, but PyGTK is very old and depreciated - I do not want to use it.

How can I make GTK+ 3 work with OpenCV? Is it even possible?

Upvotes: 0

Views: 837

Answers (1)

foo
foo

Reputation: 65

cv2.imshow is probably not supposed to be used in GUIs, but for a quick-and-dirty solution see the following code (tested on gtk 3.42 @ python 3.10.1):

import time
import threading
import cv2
import numpy

cv2.imshow('warmup', numpy.zeros((100,100,3)))
time.sleep(0.5)
cv2.destroyAllWindows()

import gi
gi.require_version("Gtk", "3.0")
from gi.repository import Gtk

demo = Gtk.Window()
btn = Gtk.Button.new_with_label('Input test')
btn.connect('clicked', lambda _: print('Input works'))
demo.add(btn)

# Capturing from webcam here, but other sources will probably work too
cap = cv2.VideoCapture(0)
cap.open(0)

def cv2_loop():
  while cap.isOpened():
    ret, frame = cap.read()
    if not ret: break

    cv2.imshow('capture', frame)

cv2_thread = threading.Thread(target=cv2_loop)
cv2_thread.start()

def done(*args):
  cap.release()
  cv2.destroyAllWindows()
  cv2_thread.join()
  Gtk.main_quit()

demo.connect('destroy', done)
demo.show_all()

Gtk.main()
cv2_thread.join()

The trick is to force-initialize OpenCV before you import GTK stuff.

Upvotes: 1

Related Questions