使用Numpy图像阵列数据更新Kivy Widget

时间:2022-03-03 10:17:13

I have a Kivy widget that I would like to act as a placeholder for a live preview from a webcam. I've already got the webcam stream part figured out, but I can't quite get the stream to fill the empty Image widget (assuming I should even be using an image widget and not something else).

我有一个Kivy小部件,我想充当占位符,从网络摄像头进行实时预览。我已经弄清楚了网络摄像头流部分,但是我不能完全获得流来填充空的Image小部件(假设我甚至应该使用图像小部件而不是其他东西)。

For the record, I'm not using the Camera widget because it does not work well with the Raspberry Pi camera, which is not a USB webcam.

为了记录,我没有使用Camera小部件,因为它与Raspberry Pi相机不兼容,后者不是USB网络摄像头。

Here is the code for my Camera Widget class:

这是我的Camera Widget类的代码:

class CV2Camera(BoxLayout):    
def __init__(self, **kwargs):
    super(CV2Camera, self).__init__(**kwargs)
    self.vs = WebcamVideoStream(src=0).start()

def _finish_init(self, dt):
    Clock.schedule_interval(self.update, .05)

def update(self, dt):
    self.image = self.vs.read()
    self.image = imutils.resize(self.image, width=1080)
    self.image = np.fliplr(self.image)

    self.video_texture = Texture.create(size=(self.image.shape[1], self.image.shape[0]), colorfmt='bgr')
    self.video_texture.blit_buffer(self.image.tostring(), colorfmt='bgr', bufferfmt='ubyte')
    self.video_panel = self.ids['camera_preview']
    with self.video_panel.canvas as canvas:
        Rectangle(texture=self.video_texture, pos=self.video_panel.pos, size=self.video_panel.size)

And here is my layout declaration:

这是我的布局声明:

<CV2Camera>
canvas.before:
    PushMatrix
canvas.after:
    PopMatrix

<PhotoBooth>:
    Screen:
        name: 'screen1'
        GridLayout:
            cols: 2
            orientation: 'horizontal'
            FloatLayout:
                size_hint: 4, 1
                CV2Camera:
                    id: camera
                    orientation: 'horizontal'
                    Image:
                        id: camera_preview
            GridLayout:
                cols: 1
                Button:
                    text: "<-Previous Frame"
                Button:
                    text: "Next Frame->"
                Button:
                    text: "Take Picture!"
                    on_press: root.capture()

This code runs fine, but all I get is a gray square where my image/camera preview should be showing up. I'm new to Kivy's architecture, but the examples from around the web that got me here (such as this SO thread and this Github project) seem to indicate this should work. Thanks.

这段代码运行正常,但我得到的是一个灰色方块,我的图像/相机预览应该出现。我是Kivy架构的新手,但是网络上的例子(例如这个SO线程和这个Github项目)似乎表明这应该有用。谢谢。

1 个解决方案

#1


1  

I don't think i have a definite solution here, but some remarks/questions that may help go forward.

我不认为我在这里有一个明确的解决方案,但一些可能有助于推进的言论/问题。

  • I don't think you need to recreate the texture and the rectangle every update, you should be able to create the texture and canvas instruction in __init__ and just do the blit_buffer part in each update.

    我不认为你需要在每次更新时重新创建纹理和矩形,你应该能够在__init__中创建纹理和画布指令,并在每次更新时执行blit_buffer部分。

  • I don't see any call to _finish_init. Is it supposed to be called by the start() method or something? Also, did you really want to set the result of start() in the vs attribute, and not the WebcamVideoFrame object itself? (ok, it actually returns self, if i can assume it's this code that you use https://github.com/jrosebr1/imutils/tree/master/imutils/video)

    我没有看到对_finish_init的任何调用。它应该由start()方法调用吗?另外,你真的想在vs属性中设置start()的结果,而不是WebcamVideoFrame对象本身吗? (好吧,它实际上会返回self,如果我可以假设它是你使用的代码https://github.com/jrosebr1/imutils/tree/master/imutils/video)

  • You can certainly get ride of your (currently misindented, at least in the code you put here), canvas instructions in the <CV2Camera> rule.

    您当然可以在 规则中获取您的(目前是错误的,至少在您放在此处的代码中),画布说明。

  • Apparently you should be able to check if the stream was read correctly using self.vs.grabbed.

    显然,您应该能够使用self.vs.grabbed检查是否正确读取了流。

  • You don't need to use an Image, any Widget has a canvas in kivy, and creating a Rectangle on it, to display the texture should work without issue, assuming the image is correctly encoded/converted).

    您不需要使用Image,任何Widget都有kivy的画布,并在其上创建一个Rectangle,以显示纹理应该没有问题,假设图像被正确编码/转换)。

#1


1  

I don't think i have a definite solution here, but some remarks/questions that may help go forward.

我不认为我在这里有一个明确的解决方案,但一些可能有助于推进的言论/问题。

  • I don't think you need to recreate the texture and the rectangle every update, you should be able to create the texture and canvas instruction in __init__ and just do the blit_buffer part in each update.

    我不认为你需要在每次更新时重新创建纹理和矩形,你应该能够在__init__中创建纹理和画布指令,并在每次更新时执行blit_buffer部分。

  • I don't see any call to _finish_init. Is it supposed to be called by the start() method or something? Also, did you really want to set the result of start() in the vs attribute, and not the WebcamVideoFrame object itself? (ok, it actually returns self, if i can assume it's this code that you use https://github.com/jrosebr1/imutils/tree/master/imutils/video)

    我没有看到对_finish_init的任何调用。它应该由start()方法调用吗?另外,你真的想在vs属性中设置start()的结果,而不是WebcamVideoFrame对象本身吗? (好吧,它实际上会返回self,如果我可以假设它是你使用的代码https://github.com/jrosebr1/imutils/tree/master/imutils/video)

  • You can certainly get ride of your (currently misindented, at least in the code you put here), canvas instructions in the <CV2Camera> rule.

    您当然可以在 规则中获取您的(目前是错误的,至少在您放在此处的代码中),画布说明。

  • Apparently you should be able to check if the stream was read correctly using self.vs.grabbed.

    显然,您应该能够使用self.vs.grabbed检查是否正确读取了流。

  • You don't need to use an Image, any Widget has a canvas in kivy, and creating a Rectangle on it, to display the texture should work without issue, assuming the image is correctly encoded/converted).

    您不需要使用Image,任何Widget都有kivy的画布,并在其上创建一个Rectangle,以显示纹理应该没有问题,假设图像被正确编码/转换)。