Python+Kivy如何无需预初始化相机动态调用独立相机类
问题根源
你现有的KivyCamera实现存在两个核心错误导致无法嵌入其他App或Screen:
- 继承类选择错误:KivyCamera实际是包含预览画布、启动按钮、拍照按钮的组合容器控件,你错误继承了
Image类,应该改为继承MDBoxLayout - 初始化逻辑错误:
build()是MDApp的专属生命周期方法,普通自定义Widget不会自动触发该方法,需要把UI构建逻辑放到类的__init__初始化方法中
修正后的kivycamera.py代码
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(MDBoxLayout): def __init__(self, **kwargs): super().__init__(**kwargs) # 配置容器属性 self.orientation = 'vertical' self.spacing = 10 self.padding = 20 # 添加预览画布 self.image = Image() self.add_widget(self.image) # 添加启动相机按钮 self.start_camera_button = MDFillRoundFlatButton( text="START CAMERA", pos_hint={'center_x': 0.5}, size_hint=(0.4, None), ) self.start_camera_button.bind(on_press=self.start_camera) self.add_widget(self.start_camera_button) # 添加拍照按钮 self.save_img_button = MDFillRoundFlatButton( text="TAKE PICTURE", pos_hint={'center_x': 0.5}, size_hint=(0.4, None), ) self.save_img_button.bind(on_press=self.take_picture) self.add_widget(self.save_img_button) # 预定义摄像头实例变量,避免提前初始化 self.video = None def start_camera(self, *args): # 避免重复初始化摄像头 if self.video and self.video.isOpened(): return self.video = cv2.VideoCapture(0) Clock.schedule_interval(self.load_video, 1.0 / 30.0) 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): if not hasattr(self, 'image_frame'): return timestr = time.strftime("%Y%m%d_%H%M%S") cv2.imwrite("IMG_{}.png".format(timestr), self.image_frame) cv2.imshow("Capture", self.image_frame) # 可选:资源释放方法,切换页面/关闭APP时调用避免摄像头占用 def release_camera(self): if self.video and self.video.isOpened(): self.video.release() Clock.unschedule(self.load_video)
引入方式
修正后的KivyCamera是标准的Kivy Widget,你原来的两种引入方案不需要修改业务代码,直接用即可:
方案1:独立MDApp中引入
Python代码和KV文件保持你原来的写法即可,运行后会自动渲染KivyCamera控件,点击START CAMERA才会启动摄像头。
方案2:ScreenManager中引入
UploadScreen的Python代码和KV文件保持你原来的写法即可,进入UploadScreen页面后控件会自动渲染,不会提前启动摄像头。
内容的提问来源于stack exchange,提问作者Jananda
相关产品推荐
相关产品推荐

