如何防止屏幕管理器中的 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()
方法调用的相机更新
如果你在Maff
class中定义了一个loadcamera()
方法,那么类似:
<CameraPage>:
name: "camerapage"
on_enter: maff.loadcamera()
MaFF:
id: maff
应该可以。
我正在开发一个使用 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()
方法调用的相机更新
如果你在Maff
class中定义了一个loadcamera()
方法,那么类似:
<CameraPage>:
name: "camerapage"
on_enter: maff.loadcamera()
MaFF:
id: maff
应该可以。