Python pygame.camera”的英文缩写;livefeed“;在tkinter窗口内(在raspbian上)

Python pygame.camera”的英文缩写;livefeed“;在tkinter窗口内(在raspbian上),python,tkinter,camera,pygame,Python,Tkinter,Camera,Pygame,我已经研究过在tkinter窗口中嵌入pygame窗口(参考:) 我想用它来嵌入pygame.camera模块制作的快照(可能是livefeed) 在评论中说,当评论出os.environ['SDL\u VIDEODRIVER']='windib' 然而,我无法让嵌入工作正常进行,也无法用pygame制作快照,我也无法找出问题的原因。以下是我编写的代码: 在设置os.environ['SDL\u WINDOWID']之后,必须使用pygame os.environ['SDL_WINDOWID'

我已经研究过在tkinter窗口中嵌入pygame窗口(参考:)

我想用它来嵌入pygame.camera模块制作的快照(可能是livefeed)

在评论中说,当评论出
os.environ['SDL\u VIDEODRIVER']='windib'

然而,我无法让嵌入工作正常进行,也无法用pygame制作快照,我也无法找出问题的原因。以下是我编写的代码:


在设置
os.environ['SDL\u WINDOWID']之后,必须使用
pygame

os.environ['SDL_WINDOWID'] = str(...)
pygame.init()

编辑:它适用于Linux Mint 18.2

import pygame as pg
import pygame.camera
import tkinter as tk
import os
import threading as th

#tk.Frame = tk.LabelFrame

class Viewer(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent # there is self.master which keeps parent

        self.parent.protocol('WM_DELETE_WINDOW', self.parent.destroy)

        self.screen_width = parent.winfo_screenwidth()
        self.screen_height = parent.winfo_screenheight()

        self.embed = tk.Frame(self.parent, width=650, height=490)
        self.embed.pack(side='left')

        self.buttonFrame = tk.Frame(self.parent, width=100, height=490)
        self.buttonFrame.pack(side='right')

        self.parent.update() # need it to get embed.winfo_id() in Capture

        self.c = Capture(self)

        self.refreshButton = tk.Button(self.buttonFrame,
                                 text='Refresh',
                                 command=self.refresh)
        self.refreshButton.pack()

    def refresh(self):
        self.c.snap()


class Capture():

    def __init__(self, parent):
        os.environ['SDL_WINDOWID'] = str(parent.embed.winfo_id())

        pg.display.init()
        pg.camera.init()

        self.size = (640,480)
        self.display = pg.display.set_mode(self.size)
        self.display.fill(pg.Color(255,255,255))

        pg.display.update()

        self.clist = pg.camera.list_cameras()

        if not self.clist:
            raise ValueError("Sorry, no cameras detected.")
        print('cameras:', self.clist)

        self.cam = pg.camera.Camera(self.clist[0], self.size)
        self.cam.start()

        self.snapshot = pg.surface.Surface(self.size, 0, self.display)

        self.event = th.Thread(target=self.eventCatcher)
        self.event.start()

    def snap(self):
        print('snap ready:', self.cam.query_image())
        self.cam.get_image(self.snapshot)
        self.display.blit(self.snapshot, self.snapshot.get_rect())
        pg.display.update()

    def eventCatcher(self):
        closed = False
        while not closed:
            events = pg.event.get()
            for e in events:
                if e.type == pg.QUIT:
                    self.cam.stop()
                    closed = True

root = tk.Tk()
run = Viewer(root)
root.mainloop()

Viewer
中,您有方法
refresh(self)
和按钮
self.refresh=button()
-对于python,这意味着
button
替换了方法。可能一些代码在嵌入框架中无法工作-在获得工作示例之前,开始删除代码行。谢谢!我明天会测试这个。。还感谢您指出
self.refresh
bug。以这种方式运行时,我遇到了一个内核错误(使用带有内置IPython控制台的spyder3 IDE)。摄像头检测工作正常,因为当没有检测到摄像头时,我会遇到异常。编辑:好的,很抱歉,我遗漏了您在
snap()
方法中更改的另一部分代码。现在它起作用了。非常好的帮助:)我应该在更改代码时在代码中添加注释-但我忘了;)
import pygame as pg
import pygame.camera
import tkinter as tk
import os
import threading as th

#tk.Frame = tk.LabelFrame

class Viewer(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.parent = parent # there is self.master which keeps parent

        self.parent.protocol('WM_DELETE_WINDOW', self.parent.destroy)

        self.screen_width = parent.winfo_screenwidth()
        self.screen_height = parent.winfo_screenheight()

        self.embed = tk.Frame(self.parent, width=650, height=490)
        self.embed.pack(side='left')

        self.buttonFrame = tk.Frame(self.parent, width=100, height=490)
        self.buttonFrame.pack(side='right')

        self.parent.update() # need it to get embed.winfo_id() in Capture

        self.c = Capture(self)

        self.refreshButton = tk.Button(self.buttonFrame,
                                 text='Refresh',
                                 command=self.refresh)
        self.refreshButton.pack()

    def refresh(self):
        self.c.snap()


class Capture():

    def __init__(self, parent):
        os.environ['SDL_WINDOWID'] = str(parent.embed.winfo_id())

        pg.display.init()
        pg.camera.init()

        self.size = (640,480)
        self.display = pg.display.set_mode(self.size)
        self.display.fill(pg.Color(255,255,255))

        pg.display.update()

        self.clist = pg.camera.list_cameras()

        if not self.clist:
            raise ValueError("Sorry, no cameras detected.")
        print('cameras:', self.clist)

        self.cam = pg.camera.Camera(self.clist[0], self.size)
        self.cam.start()

        self.snapshot = pg.surface.Surface(self.size, 0, self.display)

        self.event = th.Thread(target=self.eventCatcher)
        self.event.start()

    def snap(self):
        print('snap ready:', self.cam.query_image())
        self.cam.get_image(self.snapshot)
        self.display.blit(self.snapshot, self.snapshot.get_rect())
        pg.display.update()

    def eventCatcher(self):
        closed = False
        while not closed:
            events = pg.event.get()
            for e in events:
                if e.type == pg.QUIT:
                    self.cam.stop()
                    closed = True

root = tk.Tk()
run = Viewer(root)
root.mainloop()