Dish_Recognition/hik_camera_app.py

137 lines
4.5 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.

# hik_camera_app.py
# 菜品识别:仅海康相机(UI 复用 ui.classifier_ui)
import os
import sys
import threading
import time
from ctypes import WinDLL
import cv2
dll_path = r'C:\Program Files (x86)\Common Files\MVS\Runtime\Win64_x64\MvCameraControl.dll'
if not os.path.exists(dll_path):
raise FileNotFoundError(f"找不到海康 DLL:{dll_path}")
try:
MvCamCtrldll = WinDLL(dll_path)
print(f"[OK] loaded DLL: {dll_path}")
except Exception as e:
raise RuntimeError(f"加载海康 DLL 失败:{e}")
if hasattr(sys, 'frozen'):
os.environ['PYTHONIOENCODING'] = 'utf-8'
from ui.classifier_ui import BaseDishApp, run_app
try:
from camera.hik_camera_tool import HikCameraCapture
CAMERA_AVAILABLE = True
except ImportError:
CAMERA_AVAILABLE = False
print("[WARN] hik camera tool not found")
class ImageClassifierDemo(BaseDishApp):
window_title = "菜品识别系统"
app_title = "菜品识别系统"
edition_label = "海康相机版"
camera_display_name = "海康相机"
def __init__(self, root):
self.camera = None
self._frame_lock = threading.Lock()
super().__init__(root)
def auto_connect_camera(self):
if not CAMERA_AVAILABLE:
self.root.after(0, self._update_camera_ui_fail)
return
def connect_thread():
try:
self.camera = HikCameraCapture()
devices = self.camera.enum_devices()
if devices:
self.camera.connect_camera(0)
self.camera.start_grabbing()
self.camera_connected = True
self.root.after(0, self._update_camera_ui_success)
return
self.camera = None
except Exception as e:
self.camera = None
print(f"海康相机连接失败:{e}")
self.root.after(0, self._update_camera_ui_fail)
threading.Thread(target=connect_thread, daemon=True).start()
def grab_preview_frame(self):
"""内存取 BGR,供流畅预览(不落盘)。"""
if not self.camera_connected or self.camera is None:
return None
with self._frame_lock:
try:
return self.camera.grab_bgr_frame(timeout_ms=200)
except Exception as e:
print(f"海康取帧失败: {e}")
return None
def take_live_frame(self):
"""识别用:优先复用预览缓存帧;否则再取一帧并落盘。"""
frame = None
with getattr(self, "_live_lock", self._frame_lock):
latest = getattr(self, "_latest_frame", None)
if latest is not None:
try:
frame = latest.copy()
except Exception:
frame = None
if frame is None:
frame = self.grab_preview_frame()
if frame is None:
return -1, None, None
os.makedirs("images", exist_ok=True)
stamp = int(time.time() * 1000)
save_path = os.path.abspath(os.path.join("images", f"_live_frame_{stamp}.jpg"))
try:
if cv2.imwrite(save_path, frame):
self._cleanup_old_live_frames(keep=30)
return 0, save_path, frame
except Exception as e:
print(f"海康实时取帧失败: {e}")
return -1, None, None
def take_photo(self):
os.makedirs("images", exist_ok=True)
capture_time = time.strftime("%Y%m%d_%H%M%S")
save_path = f'images/capture_{capture_time}.jpg'
if not self.camera_connected or self.camera is None:
return -1, None
try:
with self._frame_lock:
ret, path = self.camera.capture_and_save_jpg(save_path, 90)
if ret == 0:
return ret, path
except Exception as e:
print(f"海康拍照失败: {e}")
return -1, None
def close_camera(self):
if self.camera is not None:
try:
self.camera.finalize()
except Exception as e:
print(f"释放海康相机失败: {e}")
finally:
self.camera = None
self.camera_connected = False
if __name__ == "__main__":
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)