【问题标题】:Record webcam video with wxpython open-Cv using control buttons?使用控制按钮使用 wxpython open-Cv 录制网络摄像头视频?
【发布时间】:2016-06-22 07:59:41
【问题描述】:

我已经设法使用 Open-CV 在 Wx-Python 窗口内流式传输网络摄像头视频,但我想使用控制按钮录制该视频。让我知道如何在单击按钮时捕获网络摄像头视频?

import wx
import vlc
import numpy as np
import time
import os
import user
import cv2.cv

class MainWindow(wx.Panel):
    def __init__(self, parent,capture):
        wx.Panel.__init__(self, parent)
        mainSizer = wx.BoxSizer(wx.VERTICAL)

# video
       videoWarper = wx.StaticBox(self,size=(640,480))
       videoBoxSizer = wx.StaticBoxSizer(videoWarper, wx.VERTICAL)
       videoFrame = wx.Panel(self, -1,size=(640,480))
       capture = ShowCapture(videoFrame, capture)
       videoBoxSizer.Add(videoFrame,0)
       mainSizer.Add(videoBoxSizer,0)

       parent.Centre()
       self.Show()
       self.SetSizerAndFit(mainSizer)

# Panels
# The first panel holds the video and it's all black
       self.videopanel = wx.Panel(self, -1)
       self.videopanel.SetBackgroundColour(wx.BLACK)

# The second panel holds controls
       ctrlpanel = wx.Panel(self, -1 )
       self.timeslider = wx.Slider(ctrlpanel, -1, 0, 0, 1000)
       self.timeslider.SetRange(0, 1000)
       pause  = wx.Button(ctrlpanel, label="Pause")
       play   = wx.Button(ctrlpanel, label="Play")
       stop   = wx.Button(ctrlpanel, label="Stop")
       record = wx.Button(ctrlpanel, label="Record")
       cancel = wx.Button(ctrlpanel, label="Cancel")
       volume = wx.Button(ctrlpanel, label="Vol")
       self.volslider = wx.Slider(ctrlpanel, -1, 0, 0, 100, size=(100, -1))

# Bind controls to events
       self.Bind(wx.EVT_BUTTON, self.OnPlay, play)
       self.Bind(wx.EVT_BUTTON, self.OnPause, pause)
       self.Bind(wx.EVT_BUTTON, self.OnStop, stop)
       self.Bind(wx.EVT_BUTTON, self.OnRecord, record)
       self.Bind(wx.EVT_BUTTON, self.OnCancel, cancel)
       self.Bind(wx.EVT_BUTTON, self.OnToggleVolume, volume)
       self.Bind(wx.EVT_SLIDER, self.OnSetVolume, self.volslider)

# Give a pretty layout to the controls
       ctrlbox = wx.BoxSizer(wx.VERTICAL)
       box = wx.BoxSizer(wx.HORIZONTAL)

# box contains some buttons and the volume controls
       box.Add(play, flag=wx.RIGHT, border=5)
       box.Add(pause)
       box.Add(stop)
       box.Add(record)
       box.Add(cancel)
       box.Add((-1, -1), 1)
       box.Add(volume)
       box.Add(self.volslider, flag=wx.TOP | wx.LEFT, border=5)

# Merge box1 and box2 to the ctrlsizer
       ctrlbox.Add(box, flag=wx.EXPAND, border=10)
       ctrlpanel.SetSizer(ctrlbox)

# Put everything togheter
       sizer = wx.BoxSizer(wx.VERTICAL)
       sizer.Add(ctrlpanel, flag=wx.EXPAND | wx.BOTTOM | wx.TOP, border=10)
       self.SetSizer(sizer)
       self.SetMinSize((350, 300))

# finally create the timer, which updates the timeslider
       self.timer = wx.Timer(self)
       self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)

# VLC player controls
       self.Instance = vlc.Instance()
       self.player = self.Instance.media_player_new()

    def OnClose(self, evt):
       """Closes the window.
       """
       self.Close()

    def OnOpen(self, evt):
       """Pop up a new dialow window to choose a file, then play the selected file.
       """
# if a file is already running, then stop it.
       self.OnStop(None)

# Create a file dialog opened in the current home directory, where
# you can display all kind of files, having as title "Choose a file".
       dlg = wx.FileDialog(self, "Choose a file", user.home, "",
                        "*.*", wx.OPEN)
       if dlg.ShowModal() == wx.ID_OK:
           dirname = dlg.GetDirectory()
           filename = dlg.GetFilename()
# Creation
       self.Media =  self.Instance.media_new(unicode(os.path.join(dirname, filename)))
       self.player.set_media(self.Media)
# Report the title of the file chosen
       title = self.player.get_title()
# if an error was encountred while retriving the title, then use
# filename
       if title == -1:
           title = filename
           self.SetTitle("%s - wxVLCplayer" % title)

# set the window id where to render VLC's video output
       self.player.set_xwindow(self.videopanel.GetHandle())
# FIXME: this should be made cross-platform
       self.OnPlay(None)

# set the volume slider to the current volume
      self.volslider.SetValue(self.player.audio_get_volume() / 2)

# finally destroy the dialog
      dlg.Destroy()

    def OnPlay(self, evt):
      """Toggle the status to Play/Pause.

      If no file is loaded, open the dialog window.
      """
# check if there is a file to play, otherwise open a
# wx.FileDialog to select a file
      if not self.player.get_media():
        self.OnOpen(None)
      else:
# Try to launch the media, if this fails display an error message
        if self.player.play() == -1:
            self.errorDialog("Unable to play.")
        else:
            self.timer.Start()

    def OnPause(self, evt):
      """Pause the player.
      """
      self.player.pause()

    def OnStop(self, evt):
      """Stop the player.
      """
      self.player.stop()
# reset the time slider
      self.timeslider.SetValue(0)
      self.timer.Stop()

# -------begin capturing and saving video
    def OnRecord(self, evt):
      capture=cv2.VideoCapture(0)
      if (not capture.isOpened()):
        print "Error"    
# video recorder
# Define the codec and create VideoWriter object
      fourcc = cv2.cv.FOURCC('M','P','E','G')
      out = cv2.VideoWriter('output.mp4',fourcc, 20.0, (640,480), isColor=True)    
      while(capture.isOpened()):
         ret, frame = capture.read()
         if ret==True:
# write the flipped frame
             out.write(frame) 
             cv2.imshow('frame',frame)
             if cv2.waitKey(1) & 0xFF == ord('q'):
                 break
         else:
             break

   def OnCancel(self, evt):
      out = cv2.VideoWriter()
      capture.release()
      out.release()
      cv2.destroyAllWindows()

   def OnTimer(self, evt):
      """Update the time slider according to the current movie time.
      """
# since the self.player.get_length can change while playing,
# re-set the timeslider to the correct range.
      length = self.player.get_length()
      self.timeslider.SetRange(-1, length)

# update the time on the slider
      time = self.player.get_time()
      self.timeslider.SetValue(time)

   def OnToggleVolume(self, evt):
      """Mute/Unmute according to the audio button.
      """
      is_mute = self.player.audio_get_mute()

      self.player.audio_set_mute(not is_mute)
# update the volume slider;
# since vlc volume range is in [0, 200],
# and our volume slider has range [0, 100], just divide by 2.
      self.volslider.SetValue(self.player.audio_get_volume() / 2)

   def OnSetVolume(self, evt):
      """Set the volume according to the volume sider.
      """
      volume = self.volslider.GetValue() * 2
# vlc.MediaPlayer.audio_set_volume returns 0 if success, -1 otherwise
      if self.player.audio_set_volume(volume) == -1:
          self.errorDialog("Failed to set volume")

class ShowCapture(wx.Panel):

   def __init__(self, parent, capture, fps=24):
      wx.Panel.__init__(self, parent, wx.ID_ANY, (0,0), (640,480))

      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)

app = wx.App(False)
frame = wx.Frame(None, title='CamGUI')
panel = MainWindow(frame,capture)
frame.Show()
app.MainLoop()

【问题讨论】:

    标签: python-2.7 wxpython raspberry-pi2


    【解决方案1】:

    我已经修改了您的代码,以便控制按钮出现、可见并具有功能。但是您仍然必须处理这些功能。您还可以对滑块进行编程以跳转到视频中的点:

    import wx
    import vlc
    import numpy as np
    import sys
    import time
    import os
    import user
    import cv2.cv
    
    class MainWindow(wx.Frame):
        def __init__(self, parent, title):
            wx.Frame.__init__(self, parent)
            self.size = (640,480)
            self.Bind(wx.EVT_CLOSE, self.OnClose)
            mainSizer = wx.BoxSizer(wx.VERTICAL)
            self.title = title
            self.SetTitle(self.title)
            self.panel = wx.Panel(self)
            # video
            self.Playing = False
            self.capture = cv2.VideoCapture(0)
            self.videoFrame = wx.Panel(self.panel, -1, size=self.size)
            image = wx.EmptyImage(self.size[0], self.size[1])
            imageBitmap = wx.BitmapFromImage(image)
            self.videobmp = wx.StaticBitmap(self.videoFrame, wx.ID_ANY, imageBitmap)
            self.ShowCapture()
    
            videoSizer = wx.BoxSizer(wx.HORIZONTAL)
            videoSizer.Add(self.videoFrame, 0)
    
            mainSizer.Add(videoSizer, 0)
    
            # The second panel holds controls
            ctrlbox = wx.BoxSizer(wx.VERTICAL)
            # ctrlpanel = wx.Panel(self, -1 )
            self.timeslider = wx.Slider(self.panel, -1, 0, 0, 1000)
            self.timeslider.SetRange(0, 1000)
            ctrlbox.Add(self.timeslider, flag=wx.EXPAND, border=10)
            box = wx.BoxSizer(wx.HORIZONTAL)
            pause  = wx.Button(self.panel, label="Pause")
            play   = wx.Button(self.panel, label="Play")
            stop   = wx.Button(self.panel, label="Stop")
            record = wx.Button(self.panel, label="Record")
            cancel = wx.Button(self.panel, label="Cancel")
            volume = wx.Button(self.panel, label="Vol")
            self.volslider = wx.Slider(self.panel, -1, 0, 0, 100, size=(100, -1))
            self.volslider.SetValue(50)
            # Bind controls to events
            self.Bind(wx.EVT_BUTTON, self.OnPlay, play)
            self.Bind(wx.EVT_BUTTON, self.OnPause, pause)
            self.Bind(wx.EVT_BUTTON, self.OnStop, stop)
            self.Bind(wx.EVT_BUTTON, self.OnRecord, record)
            self.Bind(wx.EVT_BUTTON, self.OnCancel, cancel)
            self.Bind(wx.EVT_BUTTON, self.OnToggleVolume, volume)
            self.Bind(wx.EVT_SLIDER, self.OnSetVolume, self.volslider)
    
            # box contains some buttons and the volume controls
            box.Add(play, flag=wx.RIGHT, border=5)
            box.Add(pause)
            box.Add(stop)
            box.Add(record)
            box.Add(cancel)
            box.Add((-1, -1), 1)
            box.Add(volume)
            box.Add(self.volslider, flag=wx.TOP | wx.LEFT, border=5)
    
            # Merge box1 and box2 to the ctrlsizer
            ctrlbox.Add(box, flag=wx.EXPAND, border=10)
            # ctrlpanel.SetSizer(ctrlbox)
            mainSizer.Add(ctrlbox, 0)
    
            # finally create the timer, which updates the timeslider
            self.timer = wx.Timer(self)
            self.Bind(wx.EVT_TIMER, self.OnTimer, self.timer)
    
            # VLC player controls
            self.Instance = vlc.Instance()
            self.player = self.Instance.media_player_new()
    
            self.panel.SetSizer(mainSizer)
            mainSizer.Fit(self)
            # self.SetSizerAndFit(mainSizer)
            self.Centre()
            self.Show()
    
        def OnClose(self, evt):
           """Closes the window.
           """
           # self.Close()
           self.Destroy()
    
        def OnOpen(self, evt):
           """Pop up a new dialow window to choose a file, then play the selected file.
           """
           # if a file is already running, then stop it.
           self.OnStop(None)
    
           # Create a file dialog opened in the current home directory, where
           # you can display all kind of files, having as title "Choose a file".
           dlg = wx.FileDialog(self, "Choose a file", user.home, "",
                            "*.*", wx.OPEN)
           if dlg.ShowModal() == wx.ID_OK:
               self.Playing = True
               dirname = dlg.GetDirectory()
               filename = dlg.GetFilename()
               # Creation
               self.Media =  self.Instance.media_new(unicode(os.path.join(dirname, filename)))
               self.player.set_media(self.Media)
               # Report the title of the file chosen
               title = self.player.get_title()
               # if an error was encountred while retriving the title, then use
               # filename
               if title == -1:
                   title = filename
                   self.SetTitle("%s - wxVLCplayer" % title)
    
               # set the window id where to render VLC's video output
               # set the window id where to render VLC's video output
    
               # handle = self.videopanel.GetHandle()
               handle = self.videoFrame.GetHandle()
               if sys.platform.startswith('linux'): # for Linux using the X Server
                   self.player.set_xwindow(handle)
               elif sys.platform == "win32": # for Windows
                   self.player.set_hwnd(handle)
               elif sys.platform == "darwin": # for MacOS
                   self.player.set_nsobject(handle)
    
               self.OnPlay(None)
    
               # set the volume slider to the current volume
               self.volslider.SetValue(self.player.audio_get_volume() / 2)
    
               # finally destroy the dialog
           dlg.Destroy()
    
        def OnPlay(self, evt):
          """Toggle the status to Play/Pause.
    
          If no file is loaded, open the dialog window.
          """
          # check if there is a file to play, otherwise open a
          # wx.FileDialog to select a file
          if not self.player.get_media():
            self.OnOpen(None)
          else:
          # Try to launch the media, if this fails display an error message
            if self.player.play() == -1:
                self.errorDialog("Unable to play.")
            else:
                self.timer.Start()
                self.Playing = True
    
        def OnPause(self, evt):
          """Pause the player.
          """
          self.player.pause()
          self.Playing = True
    
        def OnStop(self, evt):
          """Stop the player.
          """
          self.player.stop()
          # reset the time slider
          self.timeslider.SetValue(0)
          self.timer.Stop()
          self.Playing = False
    
          # -------begin capturing and saving video
        def OnRecord(self, evt):
          # capture=cv2.VideoCapture(0)
          if (not self.capture.isOpened()):
            print "Error"    
          # video recorder
          # Define the codec and create VideoWriter object
          fourcc = cv2.cv.FOURCC('M','P','E','G')
          out = cv2.VideoWriter('output.mp4',fourcc, 20.0, (640,480), isColor=True)    
          while(self.capture.isOpened()):
             ret, frame = self.capture.read()
             if ret==True:
                 # write the flipped frame
                 out.write(frame) 
                 cv2.imshow('frame',frame)
                 if cv2.waitKey(1) & 0xFF == ord('q'):
                     break
             else:
                 break
    
        def OnCancel(self, evt):
          out = cv2.VideoWriter()
          self.capture.release()
          out.release()
          cv2.destroyAllWindows()
    
        def OnTimer(self, evt):
          """Update the time slider according to the current movie time.
          """
          # since the self.player.get_length can change while playing,
          # re-set the timeslider to the correct range.
          length = self.player.get_length()
          self.timeslider.SetRange(-1, length)
    
          # update the time on the slider
          time = self.player.get_time()
          self.timeslider.SetValue(time)
    
        def OnToggleVolume(self, evt):
          """Mute/Unmute according to the audio button.
          """
          is_mute = self.player.audio_get_mute()
    
          self.player.audio_set_mute(not is_mute)
          # update the volume slider;
          # since vlc volume range is in [0, 200],
          # and our volume slider has range [0, 100], just divide by 2.
          self.volslider.SetValue(self.player.audio_get_volume() / 2)
    
        def OnSetVolume(self, evt):
          """Set the volume according to the volume sider.
          """
          volume = self.volslider.GetValue() * 2
          # vlc.MediaPlayer.audio_set_volume returns 0 if success, -1 otherwise
          if self.player.audio_set_volume(volume) == -1:
              self.errorDialog("Failed to set volume")
    
        def ShowCapture(self, fps=24):
          ret, self.frame = self.capture.read()
          self.height, self.width = self.frame.shape[:2]
          # self.SetSize((self.width, self.height))
          self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
          self.bmp = wx.BitmapFromBuffer(self.width, self.height, self.frame)
          self.timer2 = wx.Timer(self)
          self.timer2.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):
          if not self.Playing:
            ret, self.frame = self.capture.read()
            if ret:
              self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
              self.bmp.CopyFromBuffer(self.frame)
              self.videobmp.SetBitmap(self.bmp)
              self.Refresh()
    
    app = wx.App(False)
    frame = MainWindow(None, title='CamGUI')
    frame.Show()
    app.MainLoop()
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-09-10
      • 2017-09-16
      • 2020-11-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-02-28
      相关资源
      最近更新 更多