Reputation: 1
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
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