I am trying to use wxPython for a GUI that has one half being OpenCV webcam video, and the other half being other components from wxPython (buttons, textboxes, etc.).
I have been able to get an OpenCV window into my wxPython frame with this code:
import wx
import cv2
vs = cv2.VideoCapture(0)
class ImagePanel(wx.Panel):
def __init__(self, parent, fps=15):
super().__init__(parent)
ret, frame = vs.read()
frame = cv2.flip(frame, 1)
height, width = frame.shape[:2]
parent.SetSize((width, height))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp = wx.Bitmap.FromBuffer(width, height, frame)
self.timer = wx.Timer(self)
self.timer.Start(1000. / fps)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_TIMER, self.NextFrame)
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0)
def NextFrame(self, event):
ret, frame = vs.read()
if ret:
frame = cv2.flip(frame, 1)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp.CopyFromBuffer(frame)
self.Refresh()
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='User Capture')
self.vs = vs
ImagePanel(self)
self.Show()
if __name__ == '__main__':
app = wx.App(redirect=False)
frame = MainFrame()
app.MainLoop()
I then tried to create a main panel that will hold the OpenCV panel and other components (right now a button)
import wx
import cv2
import threading
vs = cv2.VideoCapture(0)
class ImagePanel(wx.Panel):
def __init__(self, parent, fps=15):
super().__init__(parent)
ret, frame = vs.read()
frame = cv2.flip(frame, 1)
height, width = frame.shape[:2]
parent.SetSize((width, height))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp = wx.Bitmap.FromBuffer(width, height, frame)
self.timer = wx.Timer(self)
self.timer.Start(1000. / fps)
self.Bind(wx.EVT_PAINT, self.OnPaint)
self.Bind(wx.EVT_TIMER, self.NextFrame)
def OnPaint(self, evt):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0)
def NextFrame(self, event):
ret, frame = vs.read()
if ret:
frame = cv2.flip(frame, 1)
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp.CopyFromBuffer(frame)
self.Refresh()
class MainPanel(wx.Panel):
def __init__(self, frame):
wx.Panel.__init__(self, frame)
main_sizer = wx.BoxSizer(wx.VERTICAL)
button_sizer = self._button_sizer(frame)
img = ImagePanel(self)
main_sizer.Add(img)
main_sizer.Add(button_sizer)
self.SetSizer(main_sizer)
self.Show()
def _button_sizer(self, frame):
snap = wx.Button(self, label='Snap')
button_sizer = wx.BoxSizer(wx.HORIZONTAL)
button_sizer.Add(snap)
button_sizer.Add((-1, -1), proportion=1)
return button_sizer
class MainFrame(wx.Frame):
def __init__(self):
super().__init__(None, title='User Capture')
self.vs = vs
MainPanel(self)
self.Show()
if __name__ == '__main__':
app = wx.App(redirect=False)
frame = MainFrame()
app.MainLoop()
Which results in this:
I can say that my implementation of wxPython is clearly not good, so I need some help on how to do this properly


