Roger.C
Roger.C

Reputation: 81

Flicker with wxpython displaying webcam video

I am new to python. I am trying to write a motion detection app. Currently, I am trying to get the webcam video to display on the screen. Current code right now has no flicker at first, but after any resizing, the flicker will come back. Any clue? Also, why doesn't it work without self.Refresh() in the timer event, isn't paint event always happening unless the frame is minimized? Thanks in advance.

import wx
import cv

class LiveFrame(wx.Frame):

  fps = 30


  def __init__(self, parent):
    wx.Frame.__init__(self, parent, -1, title="Live Camera Feed")

    self.SetDoubleBuffered(True)
    self.capture = None
    self.bmp = None
    #self.displayPanel = wx.Panel(self,-1)

    #set up camaera init
    self.capture = cv.CaptureFromCAM(0)
    frame = cv.QueryFrame(self.capture)
    if frame:
      cv.CvtColor(frame,frame,cv.CV_BGR2RGB)
      self.bmp = wx.BitmapFromBuffer(frame.width,frame.height,frame.tostring())
      self.SetSize((frame.width,frame.height))
    self.displayPanel = wx.Panel(self,-1)

    self.fpstimer = wx.Timer(self)
    self.fpstimer.Start(1000/self.fps)
    self.Bind(wx.EVT_TIMER, self.onNextFrame, self.fpstimer)
    self.Bind(wx.EVT_PAINT, self.onPaint)

    self.Show(True)

  def updateVideo(self):
    frame = cv.QueryFrame(self.capture)
    if frame:
      cv.CvtColor(frame,frame,cv.CV_BGR2RGB)
      self.bmp.CopyFromBuffer(frame.tostring())
      self.Refresh()


  def onNextFrame(self,evt):
    self.updateVideo()
    #self.Refresh()
    evt.Skip()

  def onPaint(self,evt):
    #if self.bmp:
    wx.BufferedPaintDC(self.displayPanel, self.bmp)

    evt.Skip()

if __name__=="__main__":
    app = wx.App()
    app.RestoreStdio()
    LiveFrame(None)
    app.MainLoop()

Upvotes: 3

Views: 2664

Answers (2)

Roger.C
Roger.C

Reputation: 81

I have found the solution to this problem. The flickering came from the panel clearing its background. I had to create a panel instance and have its EVT_ERASE_BACKGROUND bypass. Another thing is that I had to put the webcam routine inside that panel and have BufferPaintedDC drawing on the panel itself. For some reason, flicker still persist if wx.BufferedPaintedDC is drawing from the frame to self.displaypanel .

Upvotes: 5

Mike Driscoll
Mike Driscoll

Reputation: 33071

When you're drawing, you just have to call Refresh. It's a requirement. I don't remember why. To get rid of flicker, you'll probably want to read up on DoubleBuffering: http://wiki.wxpython.org/DoubleBufferedDrawing

Or maybe you could use the mplayer control. There's an example here: http://www.blog.pythonlibrary.org/2010/07/24/wxpython-creating-a-simple-media-player/

Upvotes: 1

Related Questions