Kivy相机作为KV语言小部件

4

我正在使用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)

虽然这样做可以运行,但我更希望将UI组件从python移动到kv语言文件中。

问题是如何在kv文件中“描述”self.my_camera

我不确定是否应该将KivyCamera类作为widgetkv文件中继承。

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文件中。
有什么建议吗?
1个回答

4

或许这个例子可以帮助你。

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

刚试了你的建议,但是它只生成一个灰色的屏幕,没有其他东西。我猜这是来自于 Window.clearcolor = (.4,.4,.4,1) - tomdertech
这可能是由于您的.py和.kv文件的文件名引起的。只需将它们命名为qrtest.py和qrtest.kv,然后再试一次。 - Bill Bridge
可以!不过一段时间后我会收到内存异常。[WARNING] [GL ] BGRA 纹理支持不可用 Exception Exception: Exception('无法为纹理分配内存(大小为921600)',) in 'kivy.graphics.texture.Texture.allocate' ignored 我应该发起另一个问题吗? - tomdertech
我已经让它运行了30分钟,没有任何问题。所以无法重现你的问题。 - Bill Bridge
请问您是否可以勾选答案,以表示它是您正在寻找的答案? - Bill Bridge

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接