如何使用kivy在python中动态访问单独的相机类(无需预先初始化相机)



我已经使用python+kivy(kivycamera.py)编写了一个相机访问类,它正在运行。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()

只有在需要时,我才能将此类添加到另一个MDApp或Screen。我尝试了以下方法,但都没有成功。不要预先初始化摄像头。只能通过按钮操作激活摄像头。

在单独的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定义,将其基类更改为某个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__()调用)来消除CCD_10,并通过使KivyCamera扩展MDBoxLayout来消除CCD13变量。

最新更新