使用控制按钮使用wxpython open-Cv录制网络摄像头视频?

时间:2016-06-22 07:59:41

标签: python-2.7 wxpython raspberry-pi2

我已经设法使用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()

1 个答案:

答案 0 :(得分:0)

我修改了你的代码,以便控制按钮出现,可见并具有功能。但是你仍然需要处理这些功能。您还可以将滑块编程为跳转到视频中的点:

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()