# usb_camera_app.py # 菜品识别:仅 USB 相机(UI 复用 ui.classifier_ui) import os import sys import threading import time import cv2 if hasattr(sys, 'frozen'): os.environ['PYTHONIOENCODING'] = 'utf-8' from ui.classifier_ui import BaseDishApp, run_app class ImageClassifierDemo(BaseDishApp): window_title = "菜品识别系统" app_title = "菜品识别系统" edition_label = "USB 相机版" camera_display_name = "USB相机" def __init__(self, root): self.cap = None self._frame_lock = threading.Lock() super().__init__(root) def auto_connect_camera(self): def connect_thread(): try: self.cap = cv2.VideoCapture(0) self.cap.set(cv2.CAP_PROP_BUFFERSIZE, 1) self.cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640) self.cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480) if self.cap.isOpened(): self.camera_connected = True self.root.after(0, self._update_camera_ui_success) return self.cap = None except Exception as e: self.cap = None print(f"USB相机连接失败:{e}") self.root.after(0, self._update_camera_ui_fail) threading.Thread(target=connect_thread, daemon=True).start() def grab_preview_frame(self): if not self.camera_connected or self.cap is None: return None with self._frame_lock: try: # 丢掉缓冲旧帧,取最新 for _ in range(2): self.cap.grab() ret, frame = self.cap.read() if ret and frame is not None and frame.size > 0: return frame except Exception as e: print(f"USB取帧失败: {e}") return None def take_photo(self): if not self.camera_connected or self.cap is None: return -1, None os.makedirs("images", exist_ok=True) capture_time = time.strftime("%Y%m%d_%H%M%S") save_path = os.path.abspath(f'images/capture_{capture_time}.jpg') try: frame = self.grab_preview_frame() if frame is None: return -1, None if cv2.imwrite(save_path, frame): return 0, save_path except Exception as e: print(f"USB拍照失败: {e}") return -1, None def close_camera(self): if self.cap is not None: self.cap.release() self.cap = None self.camera_connected = False if __name__ == "__main__": # 与界面一同启动本机客户端服务(媒体 HTTP :9100;排餐/设备状态在 BaseDishApp 内拉起) try: from service.media_server import ensure_media_server ensure_media_server() except Exception as exc: print(f'[WARN] media server start failed: {exc}') run_app(ImageClassifierDemo)