Opencv与wxpython的集成
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Opencv与wxpython的集成相关的知识,希望对你有一定的参考价值。
我只是想将来自我的网络摄像头的opencv视频流整合到一个比highgui所能提供的更复杂的gui中,没有什么可以只看几个按钮和其他东西,但事实证明它不是那么微不足道。我找不到任何基本的例子,我可以从中开始设计gui。我尝试将这个code转换为新的opencv界面,结果非常糟糕。我是opencv,numpy和gui设计的新手。有时候会播放视频,但大部分时间它只是挂在那里。我猜我的一个错误可能是在wx.BitmapFromBuffer(col,row,img)中,因为在旧版本中他们使用了pil图像格式,现在它使用numpy数组,因此在原始代码中使用了pil函数“imageData”,而不是正如我所做的那样直接传递numpy数组。任何帮助,它真的很感激。
这是我的代码转换。
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()
答案
以下示例代码在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()
另一答案
您必须设置面板的大小以显示捕获的图像。我使用了你的代码而且我添加了“
self.SetSize(width,height)
没关系
另一答案
我有代码解决了上面的问题,但不幸的是我只能在wx.Python 2.8上运行它。对于最新的Phoenix版本(版本> 4.00),没有可见的视频面板。任何需要改变的想法?代码:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import numpy as np
import cv2
import wx
import sys, time
wxversion = wx.__version__
class webcamPanel(wx.Panel):
def __init__(self, parent, camera, fps=10, pause=False, mirror=False):
wx.Panel.__init__(self, parent)
self.camera = camera
return_value, self.frame = self.camera.read()
height, width = self.frame.shape[:2]
self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
if mirror:
self.frame = cv2.flip(self.frame, 1)
if wxversion[0] == "2":
self.bmp = wx.BitmapFromBuffer(width, height, self.frame)
else:
self.bmp = wx.Bitmap.FromBuffer(width, height, self.frame)
self.SetSize((width,height))
self.pause = pause
self.mirror = mirror
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 GetState(self):
return self.pause
def Kill(self):
self.Pause()
self.timer.Stop()
def Mirror(self, mirror=None):
if mirror is None:
self.mirror = not self.mirror
else:
self.mirror = mirror
def OnPaint(self, e):
dc = wx.BufferedPaintDC(self)
dc.DrawBitmap(self.bmp, 0, 0)
def Pause(self):
self.pause = True
def Start(self):
self.pause = False
def NextFrame(self, e):
if not self.pause:
return_value, self.frame = self.camera.read()
if return_value:
self.frame = cv2.cvtColor(self.frame, cv2.COLOR_BGR2RGB)
if self.mirror:
self.frame = cv2.flip(self.frame, 1)
self.bmp.CopyFromBuffer(self.frame)
self.Refresh()
class mainWindow(wx.Frame):
def __init__(self):
wx.Frame.__init__(self, None, style=wx.MINIMIZE_BOX | wx.MAXIMIZE_BOX | wx.SYSTEM_MENU | wx.CAPTION | wx.CLOSE_BOX | wx.CLIP_CHILDREN)
self.Bind(wx.EVT_CLOSE, self.CloseApp)
# Creating any menubar.
filemenu= wx.Menu()
filemenu.Append(101, "Open", "Open")
filemenu.Append(102, "Save", "Save")
filemenu.Append(wx.ID_ABOUT, "About","About")
filemenu.Append(wx.ID_EXIT,"Exit","Close")
menuBar = wx.MenuBar()
menuBar.Append(filemenu,"File")
self.SetMenuBar(menuBar)
#main ui
self.camera = cv2.VideoCapture(0)
return_value, frame = self.camera.read()
self.mirror = True
self.height, self.width, _ = frame.shape
self.iteration = 0
self.webcampanel = webcamPanel(self, self.camera, mirror=self.mirror)
self.button = wx.Button(self, label="Take Picture!")
self.button1 = wx.Button(self, label="Toggle Camera on/off")
self.button2 = wx.Button(self, label="Mirror")
main_window_sizer = wx.BoxSizer(wx.VERTICAL)
main_window_sizer.Add(self.webcampanel, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
buttonSizer = wx.BoxSizer(wx.HORIZONTAL)
buttonSizer.Add(self.button, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
buttonSizer.Add(self.button1, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
buttonSizer.Add(self.button2, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
main_window_sizer.Add(buttonSizer, 0, wx.ALIGN_CENTER_HORIZONTAL|wx.ALL, 10)
self.SetSizer(main_window_sizer)
main_window_sizer.Fit(self)
self.Bind(wx.EVT_BUTTON, self.take_picture, self.button)
self.Bind(wx.EVT_BUTTON, self.toggle, self.button1)
self.Bind(wx.EVT_BUTTON, self.toggle_mirror, self.button2)
def toggle_mirror(self, event):
self.webcampanel.Mirror()
def take_picture(self, e):
image = self.webcampanel.frame
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
# show the image in a new window!
cv2.imshow('Snapshot!', image)
def toggle(self, event):
if self.webcampanel.GetState(): # pause
self.webcampanel.Start()
else:
self.webcampanel.Pause()
def CloseApp(self, event):
self.webcampanel.Kill()
time.sleep(.2)
self.camera.release()
cv2.destroyAllWindows()
self.Destroy()
sys.exit()
if __name__ == '__main__':
app = wx.App()
window = mainWindow()
window.Show()
window.Maximize()
app.MainLoop()
以上是关于Opencv与wxpython的集成的主要内容,如果未能解决你的问题,请参考以下文章
使用 openCV 和 wxPython 从网络摄像头获取流