Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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()
like image 502
Roger.C Avatar asked Sep 02 '26 20:09

Roger.C


2 Answers

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 .

like image 133
Roger.C Avatar answered Sep 05 '26 11:09

Roger.C


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/

like image 30
Mike Driscoll Avatar answered Sep 05 '26 09:09

Mike Driscoll