Dish_Recognition/usb_camera_app.py

93 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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)