Q:

Updating Kivy Widget With Numpy Image Array Data

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).
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.
Here is the code for my Camera Widget class:
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.

A:

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

