任何用于显示摄像机实时图像的快速Python GUI
我正在尝试显示1394相机的实时图像。 目前,我的代码能够从相机获取循环中的图像,我正在寻找任何可以动态更新的快速GUI(作为一个单独的线程)。我可以在PyQt中使用QThreads来实现这一点,但是有什么建议或更快的方法来实现吗?? 这是我的密码 #循环从相机捕获帧任何用于显示摄像机实时图像的快速Python GUI,python,image,user-interface,camera,live,Python,Image,User Interface,Camera,Live,我正在尝试显示1394相机的实时图像。 目前,我的代码能够从相机获取循环中的图像,我正在寻找任何可以动态更新的快速GUI(作为一个单独的线程)。我可以在PyQt中使用QThreads来实现这一点,但是有什么建议或更快的方法来实现吗?? 这是我的密码 #循环从相机捕获帧 for frame in range(1,500): print 'frame:',frame TIME.sleep(1) #capture frame every second image_binary = pyca
for frame in range(1,500):
print 'frame:',frame
TIME.sleep(1) #capture frame every second
image_binary = pycam.cam.RetrieveBuffer()
#convert to PIL Image
pilimg = PIL.Image.frombuffer("L",(cimg.GetCols(),cimg.GetRows()),image_binary,'raw', "RGBA", 0, 1)
# At this point I want to send my image data to a GUI window and display it
谢谢。试着看看gstreamer。这是谷歌给我搜索“gstreamer 1394”的第一个结果,也是搜索“gstreamer pyqt”的第一个结果
import wx
from PIL import Image
SIZE = (640, 480)
def get_image():
# Put your code here to return a PIL image from the camera.
return Image.new('L', SIZE)
def pil_to_wx(image):
width, height = image.size
buffer = image.convert('RGB').tostring()
bitmap = wx.BitmapFromBuffer(width, height, buffer)
return bitmap
class Panel(wx.Panel):
def __init__(self, parent):
super(Panel, self).__init__(parent, -1)
self.SetSize(SIZE)
self.SetBackgroundStyle(wx.BG_STYLE_CUSTOM)
self.Bind(wx.EVT_PAINT, self.on_paint)
self.update()
def update(self):
self.Refresh()
self.Update()
wx.CallLater(15, self.update)
def create_bitmap(self):
image = get_image()
bitmap = pil_to_wx(image)
return bitmap
def on_paint(self, event):
bitmap = self.create_bitmap()
dc = wx.AutoBufferedPaintDC(self)
dc.DrawBitmap(bitmap, 0, 0)
class Frame(wx.Frame):
def __init__(self):
style = wx.DEFAULT_FRAME_STYLE & ~wx.RESIZE_BORDER & ~wx.MAXIMIZE_BOX
super(Frame, self).__init__(None, -1, 'Camera Viewer', style=style)
panel = Panel(self)
self.Fit()
def main():
app = wx.PySimpleApp()
frame = Frame()
frame.Center()
frame.Show()
app.MainLoop()
if __name__ == '__main__':
main()
我建议使用Tkinter,因为它已经是python的一部分了。我从来没有使用过PIL,但通过快速的google显示,在Tk小部件中使用PIL图像很容易(通过PIL.ImageTk.PhotoImage()方法) 如果您已经设置了一个Tkinter小部件来显示图像(标签小部件可以正常工作),那么您需要做的就是安排每隔一秒左右更新一次图像。您可以使用tkinter的
after
命令执行此操作
这里有一个例子;我没有PIL,因此它使用静态图像,但它说明了如何使用事件循环每秒获取图像:
import Tkinter
class App(Tkinter.Tk):
def __init__(self):
Tkinter.Tk.__init__(self)
self.label = Tkinter.Label(text="your image here", compound="top")
self.label.pack(side="top", padx=8, pady=8)
self.iteration=0
self.UpdateImage(1000)
def UpdateImage(self, delay, event=None):
# this is merely so the display changes even though the image doesn't
self.iteration += 1
self.image = self.get_image()
self.label.configure(image=self.image, text="Iteration %s" % self.iteration)
# reschedule to run again in 1 second
self.after(delay, self.UpdateImage, 1000)
def get_image(self):
# this is where you get your image and convert it to
# a Tk PhotoImage. For demonstration purposes I'll
# just return a static image
data = '''
R0lGODlhIAAgALMAAAAAAAAAgHCAkC6LV76+vvXeswD/ANzc3DLNMubm+v/6zS9PT6Ai8P8A////
/////yH5BAEAAAkALAAAAAAgACAAAAS00MlJq7046803AF3ofAYYfh8GIEvpoUZcmtOKAO5rLMva
0rYVKqX5IEq3XDAZo1GGiOhw5rtJc09cVGo7orYwYtYo3d4+DBxJWuSCAQ30+vNTGcxnOIARj3eT
YhJDQ3woDGl7foNiKBV7aYeEkHEignKFkk4ciYaImJqbkZ+PjZUjaJOElKanqJyRrJyZgSKkokOs
NYa2q7mcirC5I5FofsK6hcHHgsSgx4a9yzXK0rrV19gRADs=
'''
image = Tkinter.PhotoImage(data=data)
return image
if __name__ == "__main__":
app=App()
app.mainloop()
我想我应该试试pyqt4imageviewer.py这个例子,它对我很有用。 谢谢你们的帮助。 这是我修改过的代码:
from PyQt4 import QtCore, QtGui
class CameraViewer(QtGui.QMainWindow):
def __init__(self):
super(CameraViewer, self).__init__()
self.imageLabel = QtGui.QLabel()
self.imageLabel.setBackgroundRole(QtGui.QPalette.Base)
self.imageLabel.setScaledContents(True)
self.scrollArea = QtGui.QScrollArea()
self.scrollArea.setWidget(self.imageLabel)
self.setCentralWidget(self.scrollArea)
self.setWindowTitle("Image Viewer")
self.resize(640, 480)
timer = QtCore.QTimer(self)
timer.timeout.connect(self.open)
timer.start(33) #30 Hz
def open(self):
#get data and display
pilimg = getMyPILImageDatFromCamera()
image = PILQT.ImageQt.ImageQt(pilimg)
if image.isNull():
QtGui.QMessageBox.information(self, "Image Viewer","Cannot load %s." % fileName)
return
self.imageLabel.setPixmap(QtGui.QPixmap.fromImage(image))
self.imageLabel.adjustSize()
if __name__ == '__main__':
import sys
app = QtGui.QApplication(sys.argv)
CameraViewer = CameraViewer()
CameraViewer.show()
sys.exit(app.exec_())
由于好的答案非常多,我觉得我应该发布一个我专门为此构建的库:
from cvpubsubs.webcam_pub import VideoHandlerThread
import numpy as np
image_np = numpy.array(pilImage)
def update_function(frame, cam_id):
frame[...] = image_np[...]
VideoHandlerThread(video_source=image_np, callbacks=update_function).display()
事实上,如果每次image_binary都是一个新的numpy数组。如果它被分配到同一个位置,那么只需执行以下操作:
from cvpubsubs.webcam_pub import VideoHandlerThread
VideoHandlerThread(video_source=image_np).display()
我知道OpenCV几乎算不上GUI,但这是一个快速的代码操作。嘿,mg,gstreamer看起来像一个完整的包,可以完成所有事情。嗯,我有一个很好的库,可以从我的1394相机中获取自定义图像,所以我不想使用任何库。我在找一些小东西。我已经编辑了我的帖子并添加了代码。如果你有任何建议,请告诉我。最好的,最好的。对于UI集成,请查看其他答案或查看第页的[test script]()。我尝试使用Tkinter,但为了显示GUI窗口,我必须调用mainloop(),它在该点停止所有操作,即它是一个阻塞函数。我想获取图像并更新Tkinter GUI窗口。有没有办法做到这一点?@chenna:不管你使用什么工具包,你都会遇到这个问题。所有GUI工具包都需要一个事件循环。它们都有插入事件的方式(因为缺乏更好的描述)。在Tkinter的情况下,您可以在之后调用
,以便事件循环在将来的某个时候调用某些内容。我编辑了我的答案,给你一个有效的例子。谢谢布赖恩。我得到以下错误,你知道是什么引起的吗??文件“LiveCam.py”,在init self.UpdateImage(1000)文件“LiveCam.py”的第28行,在UpdateImage self.label.configure(image=self.image)文件“/usr/lib/python2.6/lib tk/Tkinter.py”的第36行,在configure return self中的第1205行,在配置self.tk.call(_flatte((self.\w,cmd))+self.\u options(cnf))类型错误:str返回非字符串(类型实例)@chenna:我不知道。我猜你的Get_image方法没有返回正确的tk图像。是的,我也这么猜。不管怎样,我尝试了PyQt4,它成功了,我已经在下面发布了我的解决方案。事实上,我有点偏向Qt,因为我已经使用它很长时间了:D。我仍然会尝试修复我的tk代码,保持u的更新。感谢BryanHi FogleBird的帮助,我得到以下错误:AttributeError:“module”对象没有属性“CallLater”。所以我使用了wx.FutureCall,然后我得到了错误AttributeError:“module”对象没有属性“BitmapFromBuffer”任何建议??您使用的是什么版本的wxPython?什么平台?Ubuntu 10.04;wxpython2.8;Python2.6I正在使用Ubuntu10.04、Python2.6和wx版本2.8.10.1(gtk2 unicode)
,它可以正常工作。