Kivy Camera как виджет языка KV

Я использую Kivy с веб-камерой. Я следовал этому примеру @Arnav использования opencv для формирования и отображать камеру как виджет. Я «расширил» макет в Python, чтобы добавить две кнопки в качестве теста, готовясь к более сложному макету.

class CamApp(App):
    def build(self):
        self.capture = cv2.VideoCapture(0)
        self.my_camera = KivyCamera(capture=self.capture, fps=30,resolution=(1920,1080))
        root = BoxLayout(orientation = 'vertical')
        root.add_widget(self.my_camera,1)
        box2 = BoxLayout(orientation = 'vertical')
        btn1 = Button(text='Hello world 1')
        btn2 = Button(text='Hello world 2')
        box2.add_widget(btn1)
        box2.add_widget(btn2)
        root.add_widget(box2, 0)
        return root
        #return Builder.load_string(kv)

Пока это работает, я бы предпочел переместить компоненты пользовательского интерфейса из python в файл kv language. Проблема в том, как «описать» self.my_camera в файле kv?

Я не уверен, следует ли наследовать класс KivyCamera как widget в файле kv, т.е.

kv = '''
<Cam1@KivyCamera>:
    texture: self.my_camera
    resolution: (1920, 1080)
    pos: self.pos
    size: self.size

Или использовать виджет canvas

<MyWidget>:
    canvas:
        Rectangle:
            source: self.my_camera
            pos: self.pos
            size: self.size

Я пробовал другие "взломанные" реализации, но во всех случаях проблема заключается в линковке через self.my_camera в файл kv.

Какие-либо предложения?


person tomdertech    schedule 29.11.2016    source источник


Ответы (1)


Возможно, этот пример может вам помочь.

# Import 'kivy.core.text' must be called in entry point script
# before import of cv2 to initialize Kivy's text provider.
# This fixes crash on app exit.

import kivy.core.text
import cv2
from kivy.app import App
from kivy.base import EventLoop
from kivy.uix.image import Image
from kivy.clock import Clock
from kivy.graphics.texture import Texture
from kivy.uix.boxlayout import BoxLayout
from kivy.core.window import Window


class KivyCamera(Image):

    def __init__(self, **kwargs):
        super(KivyCamera, self).__init__(**kwargs)
        self.capture = None

    def start(self, capture, fps=30):
        self.capture = capture
        Clock.schedule_interval(self.update, 1.0 / fps)

    def stop(self):
        Clock.unschedule_interval(self.update)
        self.capture = None

    def update(self, dt):
        return_value, frame = self.capture.read()
        if return_value:
            texture = self.texture
            w, h = frame.shape[1], frame.shape[0]
            if not texture or texture.width != w or texture.height != h:
                self.texture = texture = Texture.create(size=(w, h))
                texture.flip_vertical()
            texture.blit_buffer(frame.tobytes(), colorfmt='bgr')
            self.canvas.ask_update()


capture = None


class QrtestHome(BoxLayout):

    def init_qrtest(self):
        pass

    def dostart(self, *largs):
        global capture
        capture = cv2.VideoCapture(0)
        self.ids.qrcam.start(capture)

    def doexit(self):
        global capture
        if capture != None:
            capture.release()
            capture = None
        EventLoop.close()


class qrtestApp(App):

    def build(self):
        Window.clearcolor = (.4,.4,.4,1)
        Window.size = (400, 300)
        homeWin = QrtestHome()
        homeWin.init_qrtest()
        return homeWin

    def on_stop(self):
        global capture
        if capture:
            capture.release()
            capture = None

qrtestApp().run()

и файл kv:

<QrtestHome>:

    BoxLayout:
        orientation: "vertical"

        Label:
            height: 20
            size_hint_y: None
            text: 'Testing the camera'

        KivyCamera:
            id: qrcam

        BoxLayout:
            orientation: "horizontal"
            height: 20
            size_hint_y: None

            Button:
                id: butt_start
                size_hint: 0.5,1
                text: "start"
                on_press: root.dostart()

            Button:
                id: butt_exit
                text: "quit"
                size_hint: 0.5,1
                on_press: root.doexit()
person Bill Bridge    schedule 29.11.2016
comment
Только что попробовал ваше предложение, однако он просто создает светло-серый экран и ничего больше. Предполагая, что это от Window.clearcolor = (.4,.4,.4,1) - person tomdertech; 29.11.2016
comment
Вероятно, это вызвано именами файлов вашего . py и .kv файлы. Просто назовите их qrtest.py и qrtest.kv. И попробуй еще раз. - person Bill Bridge; 29.11.2016
comment
Это работает! Хотя через некоторое время я получаю исключение памяти. [WARNING] [GL ] BGRA texture support is not available Exception Exception: Exception('Unable to allocate memory for texture (size is 921600)',) in 'kivy.graphics.texture.Texture.allocate' ignored должен ли я поднять еще один вопрос? - person tomdertech; 29.11.2016
comment
У меня работает уже 30 минут без проблем. Так что не могу воспроизвести вашу проблему. - person Bill Bridge; 29.11.2016
comment
Пожалуйста, не могли бы вы отметить ответ, если это был ответ, который вы искали? - person Bill Bridge; 30.11.2016