[英]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.