2016-06-22 8 views
0

Ich habe es geschafft, ein Webcam-Video in einem Wx-Python-Fenster mit Open-CV zu streamen, aber ich möchte dieses Video mit Steuerschaltflächen aufnehmen. Lassen Sie mich wissen, wie Sie ein Webcam-Video während eines Klick auf eine Schaltfläche erfassen können?Webcam-Video mit wxpython open-Cv mit Steuerschaltflächen aufnehmen?

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

Antwort

0

Ich habe Ihren Code so geändert, dass Kontrollknöpfe auftauchen, sichtbar sind und Funktionen haben. Aber Sie müssen immer noch an den Funktionen arbeiten. Sie können den Schieberegler auch so programmieren, dass er zu den Punkten im Video springt:

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