【问题标题】:Any quick Python GUI to display live images from Camera任何用于显示来自相机的实时图像的快速 Python GUI
【发布时间】:2010-08-29 23:02:33
【问题描述】:

我正在尝试显示来自 1394 相机的实时图像。 目前,我的代码能够从相机循环获取图像,我正在寻找任何可以动态更新的快速 GUI(作为单独的线程)。我可以在 PyQt 中做到这一点,也许使用 QThreads 但有什么建议或更快的方法吗? 这是我的代码

#循环从相机捕捉帧

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

谢谢。

【问题讨论】:

    标签: python image user-interface camera live


    【解决方案1】:

    这里有 wxPython 代码可以做到这一点...

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

    【讨论】:

    • 嗨 FogleBird,我收到以下错误:AttributeError:“模块”对象没有属性“CallLater”。所以我使用了 wx.FutureCall,然后我得到错误 AttributeError: 'module' object has no attribute 'BitmapFromBuffer' 有什么建议吗??
    • 你使用的是什么版本的 wxPython?什么平台?
    • Ubuntu 10.04; wxPython 2.8; Python 2.6
    • 我使用的是 Ubuntu 10.04、Python 2.6 和 wx 版本 2.8.10.1 (gtk2-unicode),它可以工作。
    【解决方案2】:

    我想我会尝试 PyQt4 imageviewer.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_())
    

    【讨论】:

      【解决方案3】:

      我推荐使用 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()
      

      【讨论】:

      • 我尝试使用 Tkinter,但是当为了显示 GUI 窗口时,我不得不调用 mainloop(),它会在该点停止一切,即它是一个阻塞函数。我想获取图像并更新 Tkinter GUI 窗口。有没有办法做到这一点?
      • @chenna:无论你使用什么工具包,你都会遇到这个问题。所有的 GUI 工具包都需要一个事件循环。它们也都有插入事件的方法(因为缺乏更好的描述)。在 Tkinter 的情况下,您可以调用 after 让事件循环在将来的某个时间点调用某些东西。我已经编辑了我的答案,给你一个工作的例子。
      • 谢谢布莱恩。我收到以下错误,任何想法是什么原因造成的?文件“LiveCam.py”,第 28 行,在 init self.UpdateImage(1000) 文件“LiveCam.py”,第 36 行,在 UpdateImage self.label.configure(image=self.image) 文件中“/usr/lib/python2.6/lib-tk/Tkinter.py”,第 1205 行,在配置中返回 self._configure('configure', cnf, kw) 文件“/usr/lib/python2.6/lib- tk/Tkinter.py",第 1196 行,在 _configure self.tk.call(_flatten((self._w, cmd)) + self._options(cnf)) 中类型错误:str 返回非字符串(类型实例)
      • @chenna:我不知道。我的猜测是您的 Get_image 方法没有返回正确的 tk 图像。
      • 是的,我也猜到了。无论如何,我尝试了 PyQt4 并且它有效,我已经在下面发布了我的解决方案。我实际上对 Qt 有一点偏见,因为我已经使用了很长时间了:D。我仍然会尝试修复我的 tk 代码 n 让你保持更新。感谢布莱恩的帮助
      【解决方案4】:

      由于好的答案非常多,我觉得我应该发布一个专门为此构建的库:

      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,但这是明智的代码。

      【讨论】:

        【解决方案5】:

        尝试看看 gstreamer。 This 是 google 给我搜索“gstreamer 1394”的第一个结果,this one 是“gstreamer pyqt”的第一个结果。

        【讨论】:

        • 嘿,gstreamer 看起来像一个可以做所有事情的完整包。好吧,我很好的库可以从我的 1394 相机中获取自定义图像,所以我不想为此使用任何库。我正在寻找一些小东西。我已经编辑了我的帖子并添加了代码。如果您有任何建议,请告诉我。最好的,
        • second result by google。对于 UI 集成,请查看其他答案或查看 dc1394 home page 处的 [测试脚本](rzuser.uni-heidelberg.de/~ge6/Programing/download/…)。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多