2014年4月22日 星期二

Opencv integration with wxpython

原文出處: http://stackoverflow.com/questions/14804741/opencv-integration-with-wxpython

I just wanted to integrate the opencv video stream from my web cam into a more complex gui than highgui can offer, nothing fancy just a couple of buttons and something else, however it's proven to be not that trivial. I can't find any base example from which I can start designing the gui. I tried converting this code to the new opencv interface with quite a poor result. I'm a new to opencv, numpy and gui design. Some time does stream the video but most of the time it just hangs there. I guess my one mistake might be in wx.BitmapFromBuffer(col, row, img) since in the older version they used pil image format and now it's using numpy arrays so in the original code the used the pil function "imageData", instead of passing directly the numpy array as I'm doing. Any help it's really appreciated.

This is my code conversion.

ANSWER
The following example code works fine for me under OS X, but I've had tiny surprises with wx across platforms. It is nearly the same code, the difference is that the result from cvtColor is reassigned, and a subclass of wx.Panel (which is the important part) was added.

這篇貼文是haar這位使用者,詢問如何整合OpenCV的影片串流到一個比OpenCV內定highgui複雜的GUI介面中。原作者的從另外一個程式碼轉寫後有些問題。
經過mmgp這位使用者的修正,仍然有些問題。問題出在修正後的版本,使用cv.CV_CAP_PROP_FRAME_WIDTH以及cv.CV_CAP_PROP_FRAME_HEIGHT這兩個參數定義視訊視窗寬度與高度。但是,我使用的python不支援import cv。
最後,經過筆者這邊參考了網路上其他的資訊,可以直接用整數3,4定義視訊視窗寬度與高度,或者使用cv2.cv.CV_CAP_PROP_FRAME_WIDTH以及cv2.cv.CV_CAP_PROP_FRAME_HEIGHT這兩個參數中。所以,這個現在可以work,如下圖


目前可以work的版本是OpenCV 2.4.8。
但是,在OpenCV 3.0以後,這兩個參數並不支援,當然,3.0尚未正式release,屆時應該會改進。

import wx
import 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)
# set width
# capture.set(cv.CV_CAP_PROP_FRAME_WIDTH, 320)
# capture.set(3, 320)
# The following command works for opencv 2.4.8 not 3.0
capture.set(cv2.cv.CV_CAP_PROP_FRAME_WIDTH, 320)

# set height
# capture.set(cv.CV_CAP_PROP_FRAME_HEIGHT, 240)
#capture.set(4, 240)
capture.set(cv2.cv.CV_CAP_PROP_FRAME_HEIGHT, 240)

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

沒有留言:

張貼留言