如何防止屏幕管理器中的 Kivy 屏幕加载

How to prevent a Kivy Screen in Screen Manager From Loading

我正在开发一个使用 Kivy 作为框架的应用程序。我正在使用 ScreenManager 在小部件组之间切换,老实说,到目前为止它已经很好了。我的问题是我在图像小部件中使用 OpenCV 来显示我的网络摄像头。当 python 文件运行时,很明显小部件会立即加载,据此我的推断是每个屏幕都在启动时加载。我想阻止我的网络摄像头一直打开,并且只在加载此屏幕时启用它。如果有人有任何想法,我将永远感激

Python 将 openCV 数据传递给图像小部件的代码:

class MaFF(Image):
    def __init__(self, **kwargs):
        super(MaFF, self).__init__(**kwargs)
        self.feed = cv2.VideoCapture(0)
        self.face = cv2.CascadeClassifier('faceclassifier\haarcascade_frontalface_alt.xml')
        self.label = ['Happy', 'Sad', 'Angry', 'Disgust', 'Fear', 'Surpise', 'Neutral']
        self.img_model = load_model("./faceclassifier/emotion.h5")
        Clock.schedule_interval(self.update, 1.0 / 33.0)

    def update(self, *args):
        ret, frame = self.feed.read()
        height, width = frame.shape[:2]
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.rectangle(frame, (0, height - 50), (200, height), (0, 0, 0), thickness=cv2.FILLED)
        faces = self.face.detectMultiScale(gray, minNeighbors=5, scaleFactor=1.1, minSize=(25, 25))

        for (x, y, w, h) in faces:
            cv2.rectangle(frame, (x, y), (x + w, y + h), (100, 100, 100), 2)
            facex = frame[y:y + h, x:x + w]
            facex = cv2.cvtColor(facex, cv2.COLOR_BGR2GRAY)
            facex = cv2.resize(facex, (200, 200))
            facex = facex / 255
            facex = facex.reshape(200, 200, -1)
            facex = np.expand_dims(facex, axis=0)
            prepred_face = self.img_model.predict(facex)
            prediction = np.argmax(prepred_face, axis=1)
            lbl = None
            if prediction[0] == 0:
                lbl = 'Angry'
            if prediction[0] == 1:
                lbl = 'Happy'
            if prediction[0] == 2:
                lbl = 'Sad'
            if prediction[0] == 3:
                lbl = 'Surprised'
            cv2.putText(frame, lbl, (10, height - 20), cv2.FONT_HERSHEY_COMPLEX, 1, (255, 255, 255), 1, cv2.LINE_AA)
        bufImg = cv2.flip(frame, 0).tobytes()
        img_txtur = Texture.create(size=(frame.shape[1], frame.shape[0]), colorfmt='bgr')
        img_txtur.blit_buffer(bufImg, colorfmt='bgr', bufferfmt='ubyte')
        self.texture = img_txtur

KV Lang 文件管理屏幕和更基本的小部件。相关的是 CameraPage,通过 MainMenu 上的一个按钮调用 root.manager.current

#: import NoTransition kivy.uix.screenmanager.NoTransition

WindowManager:
    transition: NoTransition()
    StartPage:
    CreateProfile:
    Login:
    MainMenu:
    Correct:
    Incorrect:
    CameraPage:
    QuestionPage:

<CameraPage>:
    name: "camerapage"
    MaFF:

    Button:
        size_hint: (1,.1)
        text: "Go Back"
        on_press:
            root.manager.current = "mainmenu"

<StartPage>:
    name: "landing"
    GridLayout:
        cols:1
        Label:
            text: "Welcome To Smaff!\nLogin or Create a New Profile to Begin"
            halign: "center"

        Button:
            text: "Login"
            on_release:
                root.manager.current = "login"

        Button:
            text: "Create Profile"
            on_release:
                root.manager.current = "createprofile"

<Login>:
    name: "login"
    GridLayout:
        cols: 1
        Label:
            text: "Enter Login Details"
        TextInput:
            id: username
            text: "username"
            multiline: False
            write_tab: False
        TextInput:
            id: password
            text: "password"
            multiline: False
            write_tab: False
            on_text_validate:
                root.verify(username.text, password.text)
                root.manager.current = "mainmenu" if root.authenticated == True else "login"
        Button:
            text: "Login"
            on_release:
                root.verify(username.text, password.text)
                root.manager.current = "mainmenu" if root.authenticated == True else "login"
        Button:
            text: "Go Back"
            on_release:
                root.manager.current = "landing"

<CreateProfile>:
    name: "createprofile"
    Label:
        text: "This is the Create Profile Page"
    Button:
        text: "Go Back"
        on_release:
            root.manager.current = "landing"
<MainMenu>:
    name: "mainmenu"
    GridLayout:
        cols:1
        Label:
            text: "Main Menu Here"
        Button:
            text: "Make a Funny Face"
            on_release:
                root.manager.current = "camerapage"
        Button:
            text: "Play"
            on_release:
                root.manager.current = "questionpage"
        Button:
            text: "Logout"
            on_release:
                root.manager.current = "landing"


<QuestionPage>:
    name: "questionpage"
    id: questionpage
    GridLayout:
        padding: "10dp"
        cols:1
        Label:
            id: "question"
            text: root.text
            text_size: self.size
            size_hint_y: .3

        Label:
            text: root.answer

        GridLayout:
            padding: "5dp"
            rows: 2
            cols: 2
            Button:
                text: "Happy"
                on_release:
                    root.manager.current = "correct" if self.text.lower() == root.answer else "Incorrect"
                    root.refresh()

            Button:
                text: "Surprised"
                on_release:
                    root.manager.current = "correct" if self.text.lower() == root.answer else "Incorrect"
                    root.refresh()
            Button:
                text: "Angry"
                on_release:
                    root.manager.current = "correct" if self.text.lower() == root.answer else "Incorrect"
                    root.refresh()
            Button:
                text: "Sad"
                on_release:
                    root.manager.current = "correct" if self.text.lower() == root.answer else "Incorrect"
                    root.refresh()
<Correct>:
    background_color: 0, 0, 0, 0
    name: "correct"
    GridLayout:
        cols:1

        Label:
            text: "Correct!!"
        Button:
            text: "Next Question"
            on_press:
#                root.refresh()
            on_release:
                root.manager.current = 'questionpage'
<Incorrect>:
    background_color: 0, 0, 0, 0
    name: "Incorrect"
    GridLayout:
        cols:1

        Label:
            text: "Wrong Answer, Try Again!"
        Button:
            text: "Next Question"
            on_press:
#                root.refresh()
            on_release:
                root.manager.current = 'questionpage'


您可以将 MaFF class 的 __init__() 方法中的大部分(如果不是全部)代码移动到您从 on_enter() 调用的单独方法中CameraPage 的方法。您可以添加一些代码来停止可以从 CameraPage.

on_leave() 方法调用的相机更新

参见documentation

如果你在Maffclass中定义了一个loadcamera()方法,那么类似:

<CameraPage>:
    name: "camerapage"
    on_enter: maff.loadcamera() 
    MaFF:
        id: maff

应该可以。