簡體   English   中英

如何使用 kivy 在 python 中動態訪問單獨的攝像頭 class(無需預初始化攝像頭)

[英]How can I access a separate camera class dynamically in python with kivy (without pre-initialising camera)

我已經使用 python+kivy (kivycamera.py) 編寫了一個攝像頭訪問 class,它正在運行。 kivycamera.py

# from kivymd.app import MDApp
from kivy.uix.image import Image
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import cv2
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFillRoundFlatButton
import time


# class KivyCamera(MDApp):
class KivyCamera(Image):
    def build(self):
        layout = MDBoxLayout(orientation='vertical', spacing=10)

        self.image = Image()
        layout.add_widget(self.image)

        self.start_camera_button = MDFillRoundFlatButton(
            text="START CAMERA",
            pos_hint={'center_x': 0.5, 'center_y': 0.5},
            size_hint=(0.4, None),
            # size=("100dp", "100dp")
        )
        self.start_camera_button.bind(on_press=self.start_camera)
        layout.add_widget(self.start_camera_button)

        self.save_img_button = MDFillRoundFlatButton(
            text="TAKE PICTURE",
            pos_hint={'center_x': 0.5, 'center_y': 0.5},
            size_hint=(0.4, None),
            # size=("100dp", "100dp")
        )
        self.save_img_button.bind(on_press=self.take_picture)
        layout.add_widget(self.save_img_button)

        # self.video = cv2.VideoCapture(0)
        # Clock.schedule_interval(self.load_video, 1.0 / 30.0)
        # return layout
        # return self.image

    def start_camera(self, *args):
        self.video = cv2.VideoCapture(0)
        Clock.schedule_interval(self.load_video, 1.0 / 30.0)
        pass

    def load_video(self, *args):
        check, frame = self.video.read()
        if check:
            x, y, w, h = 200, 200, 250, 250
            p, q, r, s = 220, 220, 210, 210
            frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
            frame = cv2.rectangle(frame, (p, q), (p + r, q + s), (255, 0, 0), 3)
            self.image_frame = frame
            buffer = cv2.flip(frame, 0).tobytes()
            image_texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt="bgr")
            image_texture.blit_buffer(buffer, colorfmt="bgr", bufferfmt="ubyte")
            self.image.texture = image_texture

    def take_picture(self, *args):
        timestr = time.strftime("%Y%m%d_%H%M%S")
        cv2.imwrite("IMG_{}.png".format(timestr), self.image_frame)
        cv2.imshow("Hi", self.image_frame)

# KivyCamera().run()

如何僅在需要時將此 class 添加到另一個 MDApp 或屏幕。 我嘗試了以下方法,但沒有成功。 不要預先初始化相機。 僅使用按鈕操作激活相機。

在單獨的 MDApp 中

from kivymd.app import MDApp
from kivycamera import KivyCamera


class DemoApp(MDApp):
    pass
    # def build(self):
    #     self.camera = KivyCamera()
    #     self.camera.build()
    #     print(self.camera)
    #     return self.camera


if __name__ == '__main__':
    DemoApp().run()

Kivy 文件

BoxLayout:
    orientation: 'vertical'
    MDLabel:
        text: 'Hello'
    KivyCamera:

或使用屏幕管理器在單獨的屏幕內

class UploadScreen(Screen):
    pass
    # def build(self):
    #     self.my_camera = KivyCamera()
    #     self.my_camera.build()
    #     self.ids.my_camera = self.my_camera
    #     return self.my_camera

Kivy 文件

<UploadScreen>:
    name: 'upload'
    KivyCamera:

您的KivyCamera擴展了Image ,但您正在使用KivyCamera作為小部件容器。 此外,在您的build()方法中,您正在創建一個layout ,但沒有對它做任何事情。 我建議修改KivyCamera定義以將其基礎 class 更改為某個Layout (我選擇RelativeLayout )並將layout添加為子布局。 這是執行此操作的代碼的修改版本:

from kivymd.app import MDApp
from kivycamera import KivyCamera


class DemoApp(MDApp):
    def build(self):
        self.camera = KivyCamera()
        self.camera.build()
        print(self.camera)
        return self.camera


if __name__ == '__main__':
    DemoApp().run()

和 kivycamera.py:

# from kivymd.app import MDApp
from kivy.uix.image import Image
from kivy.graphics.texture import Texture
from kivy.clock import Clock
import cv2
from kivy.uix.relativelayout import RelativeLayout
from kivymd.uix.boxlayout import MDBoxLayout
from kivymd.uix.button import MDFillRoundFlatButton
import time


# class KivyCamera(MDApp):
class KivyCamera(RelativeLayout):  # make this a container
    def build(self):
        layout = MDBoxLayout(orientation='vertical', spacing=10)

        self.image = Image()
        layout.add_widget(self.image)

        self.start_camera_button = MDFillRoundFlatButton(
            text="START CAMERA",
            pos_hint={'center_x': 0.5, 'center_y': 0.5},
            size_hint=(0.4, None),
            # size=("100dp", "100dp")
        )
        self.start_camera_button.bind(on_press=self.start_camera)
        layout.add_widget(self.start_camera_button)

        self.save_img_button = MDFillRoundFlatButton(
            text="TAKE PICTURE",
            pos_hint={'center_x': 0.5, 'center_y': 0.5},
            size_hint=(0.4, None),
            # size=("100dp", "100dp")
        )
        self.save_img_button.bind(on_press=self.take_picture)
        layout.add_widget(self.save_img_button)
        self.add_widget(layout)  # add the layout to the GUI

        # self.video = cv2.VideoCapture(0)
        # Clock.schedule_interval(self.load_video, 1.0 / 30.0)
        # return layout
        # return self.image

    def start_camera(self, *args):
        self.video = cv2.VideoCapture(0)
        Clock.schedule_interval(self.load_video, 1.0 / 30.0)
        pass

    def load_video(self, *args):
        check, frame = self.video.read()
        if check:
            x, y, w, h = 200, 200, 250, 250
            p, q, r, s = 220, 220, 210, 210
            frame = cv2.rectangle(frame, (x, y), (x + w, y + h), (0, 255, 0), 3)
            frame = cv2.rectangle(frame, (p, q), (p + r, q + s), (255, 0, 0), 3)
            self.image_frame = frame
            buffer = cv2.flip(frame, 0).tobytes()
            image_texture = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt="bgr")
            image_texture.blit_buffer(buffer, colorfmt="bgr", bufferfmt="ubyte")
            self.image.texture = image_texture

    def take_picture(self, *args):
        timestr = time.strftime("%Y%m%d_%H%M%S")
        cv2.imwrite("IMG_{}.png".format(timestr), self.image_frame)
        cv2.imshow("Hi", self.image_frame)

# KivyCamera().run()

您還可以進行其他幾種簡化。 例如,您可以通過將build()方法更改為__init__()方法(必須添加super(KivyCamera, self).__init__()調用)來消除 build() 方法,並通過使KivyCamera擴展MDBoxLayout來消除layout變量。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM