I just wanted to integrate the opencv video stream from my web cam into a more
complex gui than highgui can offer, nothing fancy just a couple of buttons and
something else, however it’s proven to be not that trivial. I can’t find any
base example from which I can start designing the gui. I tried converting this
code to
the new opencv interface with quite a poor result. I’m a new to opencv, numpy
and gui design. Some time does stream the video but most of the time it just
hangs there. I guess my one mistake might be in wx.BitmapFromBuffer(col, row,
img) since in the older version they used pil image format and now it’s using
numpy arrays so in the original code the used the pil function “imageData”,
instead of passing directly the numpy array as I’m doing. Any help it’s really
appreciated.
This is my code conversion.
import wx
import cv2
class MyFrame(wx.Frame):
def __init__(self, parent):
wx.Frame.__init__(self, parent)
self.displayPanel = wx.Panel(self)
self.displayPanel.SetSize(wx.Size(800,640))
self.cam = cv2.VideoCapture(1)
self.cam.set(3, 640)
self.cam.set(4, 480)
ret, img = self.cam.read()
cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
row, col, x = img.shape
self.SetSize((col,row))
self.bmp = wx.BitmapFromBuffer(col, row, img)
self.displayPanel.Bind(wx.EVT_PAINT, self.onPaint)
self.playTimer = wx.Timer(self)
self.Bind(wx.EVT_TIMER, self.onNextFrame)
self.playTimer.Start(1000/15)
def onPaint(self, evt):
if self.bmp:
dc = wx.BufferedPaintDC(self.displayPanel)
self.PrepareDC(dc)
dc.DrawBitmap(self.bmp, 0, 0, True)
evt.Skip()
def onNextFrame(self, evt):
ret, img = self.cam.read()
if ret == True:
cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
self.bmp.CopyFromBuffer(img)
self.displayPanel.Refresh()
evt.Skip()
if __name__=="__main__":
app = wx.App()
MyFrame(None).Show()
app.MainLoop()
The following example code works fine for me under OS X, but I’ve had tiny
surprises with wx across platforms. It is nearly the same code, the difference
is that the result from cvtColor
is reassigned, and a subclass of wx.Panel
(which is the important part) was added.
import wx
import cv, cv2
class ShowCapture(wx.Panel):
def __init__(self, parent, capture, fps=15):
wx.Panel.__init__(self, parent)
self.capture = capture
ret, frame = self.capture.read()
height, width = frame.shape[:2]
parent.SetSize((width, height))
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp = wx.BitmapFromBuffer(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 = self.capture.read()
if ret:
frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
self.bmp.CopyFromBuffer(frame)
self.Refresh()
capture = cv2.VideoCapture(0)
capture.set(cv.CV_CAP_PROP_FRAME_WIDTH, 320)
capture.set(cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
app = wx.App()
frame = wx.Frame(None)
cap = ShowCapture(frame, capture)
frame.Show()
app.MainLoop()