2013-02-11 69 views
5

我只是想從我的網絡攝像頭集成opencv視頻流到一個比highgui可以提供的更復雜的gui,沒有什麼花哨只是幾個按鈕和其他東西,但它被證明不是那麼簡單。我找不到任何可以開始設計gui的基礎示例。 我試圖將這個code轉換爲新的opencv接口,結果很糟糕。我是opencv,numpy和gui設計的新手。有一段時間會播放視頻,但大多數情況下它只是掛在那裏。我想我的一個錯誤可能是wx.BitmapFromBuffer(col,row,img),因爲在舊版本中他們使用了pil image格式,現在它使用了numpy數組,所以在原始代碼中使用了pil函數「imageData」,而不是正如我所做的那樣直接傳遞numpy數組。 任何幫助它真的很感激。 color_channels_picOpencv與wxpython的集成

這是我的代碼轉換。

import wx 
import cv2 

class MyFrame(wx.Frame): 
    def __init__(self, parent): 
     wx.Frame.__init__(self, parent) 
     self.displayPanel = wx.Panel(self) 
     self.displayPanel.SetSize(wx.Size(800,640)) 

     self.cam = cv2.VideoCapture(1) 
     self.cam.set(3, 640) 
     self.cam.set(4, 480) 
     ret, img = self.cam.read() 

     cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 
     row, col, x = img.shape 
     self.SetSize((col,row)) 
     self.bmp = wx.BitmapFromBuffer(col, row, img) 
     self.displayPanel.Bind(wx.EVT_PAINT, self.onPaint) 

     self.playTimer = wx.Timer(self) 
     self.Bind(wx.EVT_TIMER, self.onNextFrame) 

     self.playTimer.Start(1000/15) 

    def onPaint(self, evt): 
     if self.bmp: 
      dc = wx.BufferedPaintDC(self.displayPanel) 
      self.PrepareDC(dc) 
      dc.DrawBitmap(self.bmp, 0, 0, True) 
     evt.Skip() 

    def onNextFrame(self, evt): 
     ret, img = self.cam.read() 
     if ret == True: 
      cv2.cvtColor(img, cv2.COLOR_BGR2RGB) 
      self.bmp.CopyFromBuffer(img) 
      self.displayPanel.Refresh() 
     evt.Skip() 

if __name__=="__main__": 
    app = wx.App() 
    MyFrame(None).Show() 
    app.MainLoop() 
+1

您的代碼不爲我工作,但微小的調整之後它就好了。我看到的問題是,例如,當我調整了流的中斷窗口的大小,直到我停止調整大小,但是如果我不觸摸窗口,它會繼續進行下去,你是否正在做其他的事情,而不僅僅是簡單地顯示這些框架? – mmgp 2013-02-11 14:04:17

+0

@mmgp你是對的,如果我評論在我設置尺寸的兩條線上,雖然我認爲我失去了顏色通道,但它仍然有效,我附加了圖片。 – wind85 2013-02-11 17:33:12

+2

關於顏色,'cvtColor'不會在原地發生,因此您必須將其結果重新分配給' img'。 – mmgp 2013-02-11 17:34:23

回答

8

下面的示例代碼可以在OS X下正常工作,但是我在跨平臺的wx上遇到了很小的驚喜。它幾乎是相同的代碼,區別在於cvtColor的結果被重新分配,並且wx.Panel(這是重要部分)的子類被添加。

import wx 
import cv, cv2 

class ShowCapture(wx.Panel): 
    def __init__(self, parent, capture, fps=15): 
     wx.Panel.__init__(self, parent) 

     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) 
capture.set(cv.CV_CAP_PROP_FRAME_WIDTH, 320) 
capture.set(cv.CV_CAP_PROP_FRAME_HEIGHT, 240) 

app = wx.App() 
frame = wx.Frame(None) 
cap = ShowCapture(frame, capture) 
frame.Show() 
app.MainLoop() 
+0

你爲什麼要將面板子類化而不是框架?不應該是wx.Frame在wx層次結構中的第一個「容器」?而第二次導入是不會在OSX上工作,或者我想從cv2訪問舊的cv你需要導入cv2.cv。你的代碼在我的機器上工作,這是一個基於Linux Debian的機器,但它不會將大小幀設置爲640X480。 – wind85 2013-02-11 18:51:40

+1

我可以在OSX中導入'cv'。該框架當然不會設置爲「640 x 480」,因爲在該示例中它被設置爲「320 x 240」,您是否嘗試更改該框架?正在創建一個'wx.Frame',它是'wx.Panel'的子類。 – mmgp 2013-02-11 18:53:29

+0

我嘗試改變大小,使用新模塊和舊模塊,但只要調整大小,它不會再刷新,並且會再次崩潰。 – wind85 2013-02-11 19:09:30

0

您必須設置面板的大小以顯示捕獲的圖像。 我用你的代碼,我補充說:「

self.SetSize(width,height) 

這是確定