Dish_Recognition/dao/settings.py

158 lines
8.7 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.

# coding=utf-8
import os
import time
CAIHUI_DATABASE = {
'name': os.environ.get('DISH_DB_NAME', 'goods'),
'host': os.environ.get('CARC_CRAWLER_DB_HOST', '127.0.0.1'),
'port': int(os.environ.get('CARC_CRAWLER_DB_PORT', 3306)),
'user': os.environ.get('CARC_CRAWLER_DB_USER', 'root'),
'password': os.environ.get('CARC_CRAWLER_DB_PASSWORD', '123456'),
}
# SQLite 本地临时缓存(识别读此库;变更后从 MySQL 拉取刷新)
DISH_SQLITE_PATH = os.environ.get(
'DISH_SQLITE_PATH',
os.path.join(os.path.dirname(__file__), 'dish_templates.db'),
)
# 本机基地编码(学菜写入 source_base_id;结果 API 的 base_id 默认也用它)
# 建议填管理系统返回的 code,例如「上海路基地-1788059884828-e55vu」
DISH_BASE_CODE = os.environ.get('DISH_BASE_CODE', 'BASE_LOCAL_01')
DISH_BASE_NAME = os.environ.get('DISH_BASE_NAME', '奥体基地')
DISH_BASE_REGION = os.environ.get('DISH_BASE_REGION', '')
# 管理系统:公开接口(X-API-Key)
# 完整 Key 见 docs/第三方接口文档_mgmt.md(含 dish_ 前缀)
DISH_MGMT_API_ORIGIN = os.environ.get(
'DISH_MGMT_API_ORIGIN',
'https://cpsb.ruimeida.cc',
).rstrip('/')
DISH_MGMT_API_URL = os.environ.get(
'DISH_MGMT_API_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/bases',
)
DISH_MGMT_RESULT_API_URL = os.environ.get(
'DISH_MGMT_RESULT_API_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/recognition-orders',
)
DISH_MGMT_UNRECOGNIZED_API_URL = os.environ.get(
'DISH_MGMT_UNRECOGNIZED_API_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/unrecognized-samples',
)
DISH_MGMT_MEAL_API_URL = os.environ.get(
'DISH_MGMT_MEAL_API_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/meal-schedules/today',
)
DISH_MGMT_DEVICE_STATUS_URL = os.environ.get(
'DISH_MGMT_DEVICE_STATUS_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/devices/status',
)
DISH_MGMT_DISHES_API_URL = os.environ.get(
'DISH_MGMT_DISHES_API_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/dishes',
)
DISH_MGMT_DISH_LEARNING_STATUS_URL = os.environ.get(
'DISH_MGMT_DISH_LEARNING_STATUS_URL',
f'{DISH_MGMT_API_ORIGIN}/api/public/dishes/learning-status',
)
DISH_MGMT_API_KEY = os.environ.get(
'DISH_MGMT_API_KEY',
'dish_a4f7a1287198179fdc6a6571aa14064c2afc6338c6730e2b668ac5be15bdf769',
)
DISH_MGMT_API_TIMEOUT = float(os.environ.get('DISH_MGMT_API_TIMEOUT', '10'))
DISH_MGMT_SYNC_ON_START = os.environ.get('DISH_MGMT_SYNC_ON_START', '1') == '1'
DISH_MGMT_MEAL_ON_START = os.environ.get('DISH_MGMT_MEAL_ON_START', '1') == '1'
# 本机设备(上报设备状态)
DISH_DEVICE_CODE = os.environ.get('DISH_DEVICE_CODE', '') or os.environ.get('DISH_BASE_CODE', DISH_BASE_CODE)
DISH_DEVICE_NAME = os.environ.get('DISH_DEVICE_NAME', '') or os.environ.get('DISH_BASE_NAME', DISH_BASE_NAME)
DISH_DEVICE_STATUS_INTERVAL = int(os.environ.get('DISH_DEVICE_STATUS_INTERVAL', '60')) # 秒
DISH_DEVICE_STATUS_ENABLED = os.environ.get('DISH_DEVICE_STATUS_ENABLED', '1') == '1'
# 启动时是否从 MySQL 拉取;后台定时同步间隔(秒,含上传队列 flush + 拉取)
DISH_SYNC_ON_START = os.environ.get('DISH_SYNC_ON_START', '1') == '1'
DISH_SYNC_INTERVAL = int(os.environ.get('DISH_SYNC_INTERVAL', 300)) # 默认 5 分钟
# 识别框是否显示「似xx 检xx」(默认关;需要时 set DISH_SHOW_BOX_SCORES=1)
DISH_SHOW_BOX_SCORES = os.environ.get('DISH_SHOW_BOX_SCORES', '0') == '1'
# 当前餐段匹配:有当日排餐时仅在「今日当前餐段」菜品中比对,未命中直接未知(不回退大库)
# 1) 最高分 ≥ 0.80 → 认定;2) 未达 0.80 但最高分 > 0.75 → 仍认定;否则未知
DISH_MEAL_SMALL_LIB_THRESHOLD = float(os.environ.get('DISH_MEAL_SMALL_LIB_THRESHOLD', '0.82'))
DISH_MEAL_SMALL_LIB_SOFT_THRESHOLD = float(os.environ.get('DISH_MEAL_SMALL_LIB_SOFT_THRESHOLD', '0.82'))
# 早于该时刻且尚无当日排餐 → 不做当前餐段限制,直接走大库
DISH_MEAL_CUTOFF_HOUR = int(os.environ.get('DISH_MEAL_CUTOFF_HOUR', '7'))
# 主食小库:不在每日排餐中,常驻候选;与「当前餐段菜品小库」双路匹配
# 环境变量 DISH_STAPLE_NAMES 逗号分隔覆盖;仅当本地模板库已有同名模板时才参与比对
_DISH_STAPLE_NAMES_DEFAULT = (
'米饭,白米饭,杂粮饭,黑米饭,馒头,花卷,包子,面条,汤面,炒饭,盖浇饭,粥,白粥,小米粥,馄饨,饺子,'
'酸奶,香蕉,苹果,梨子,葡萄,营养汤,土豆,黄瓜,山药,红薯,玉米'
)
DISH_STAPLE_NAMES = [
x.strip() for x in os.environ.get('DISH_STAPLE_NAMES', _DISH_STAPLE_NAMES_DEFAULT).split(',')
if x.strip()
]
DISH_STAPLE_LIB_THRESHOLD = float(os.environ.get('DISH_STAPLE_LIB_THRESHOLD', '0.80'))
DISH_STAPLE_LIB_SOFT_THRESHOLD = float(os.environ.get('DISH_STAPLE_LIB_SOFT_THRESHOLD', '0.81'))
# 主食与餐段菜都达标时:主食分 ≥ 菜分 - margin 则优先认主食(减轻主食被菜品抢走)
DISH_STAPLE_PRIORITY_MARGIN = float(os.environ.get('DISH_STAPLE_PRIORITY_MARGIN', '0.03'))
# 每餐开始前多少分钟拉取排餐(默认 60 = 开餐前 1 小时)
DISH_MEAL_PREFETCH_MINUTES = int(os.environ.get('DISH_MEAL_PREFETCH_MINUTES', '60'))
# 尚无餐段信息时的兜底拉取时刻(启动后第一次排餐未到位时用)
DISH_MEAL_REFRESH_HOUR = int(os.environ.get('DISH_MEAL_REFRESH_HOUR', '6'))
DISH_MEAL_REFRESH_MINUTE = int(os.environ.get('DISH_MEAL_REFRESH_MINUTE', '0'))
# 实时扫描:未知菜写入待学习前的最短稳定秒数(客人放盘短,默认 1 秒)
# 盘子移走时不刷入,避免移盘过程中的误检未知
DISH_LIVE_PENDING_STABLE_SECONDS = float(os.environ.get('DISH_LIVE_PENDING_STABLE_SECONDS', '1.0'))
# 运动判定:从动到静后,连续多少帧与静止锚点相似,才触发 YOLO 一次(按相机帧,不按秒)。
# 持续静止不再识别,须再经历「静→动→静」。默认 4 帧(约对应原 0.2s@20Hz 轮询)。
DISH_LIVE_STILL_HOLD_FRAMES = int(os.environ.get('DISH_LIVE_STILL_HOLD_FRAMES', '4'))
# 已有订单时,菜品区域相似度阈值(更低=更宽松,手在中间晃仍算静止,减少误触发)
DISH_LIVE_MOTION_SIM_WITH_ORDER = float(os.environ.get('DISH_LIVE_MOTION_SIM_WITH_ORDER', '0.970'))
# 订单防抖:菜品名称集合去重 + 时间间隔(秒),避免同一次晃动重复上传
# 默认 2s(建议 2~3s)
DISH_LIVE_ORDER_DEBOUNCE_SECONDS = float(os.environ.get('DISH_LIVE_ORDER_DEBOUNCE_SECONDS', '2'))
# 无餐盘持续该秒数后清场解锁,允许下一盘(含相同菜名)重新存图/上报
DISH_LIVE_ORDER_CLEAR_HOLD_SECONDS = float(os.environ.get('DISH_LIVE_ORDER_CLEAR_HOLD_SECONDS', '1.5'))
# 同场景去重:按预览帧计数(约 25fps,默认 40 帧 ≈ 1.6s)。
# 窗口内即使个别菜名不同,只要检测框布局相近也视为同一单(不重复上报)
DISH_LIVE_ORDER_SAME_SCENE_FRAMES = int(os.environ.get('DISH_LIVE_ORDER_SAME_SCENE_FRAMES', '40'))
# 框匹配 IoU 阈值;匹配对数占比阈值(0~1)
DISH_LIVE_ORDER_LAYOUT_IOU = float(os.environ.get('DISH_LIVE_ORDER_LAYOUT_IOU', '0.40'))
DISH_LIVE_ORDER_LAYOUT_MATCH_RATIO = float(os.environ.get('DISH_LIVE_ORDER_LAYOUT_MATCH_RATIO', '0.70'))
# YOLO 检测需直接丢弃的类别(不裁剪、不识别、不上报),逗号分隔
DISH_DETECT_FILTER_NAMES = [
x.strip() for x in os.environ.get('DISH_DETECT_FILTER_NAMES', '手,空盘').split(',')
if x.strip()
]
# 用本地视频文件夹代替相机实时流(调试/回放,主要给海康入口用)。
# 1=读 DISH_VIDEO_SOURCE_DIR,0=读相机。usb_camera_app 固定读 USB 相机,不受此项影响。
DISH_USE_VIDEO_FOLDER = os.environ.get('DISH_USE_VIDEO_FOLDER', '0') == '1'
DISH_VIDEO_SOURCE_DIR = os.environ.get('DISH_VIDEO_SOURCE_DIR', 'videos')
# 相机预览流本地录像:相机连接后自动录,只保留最近 N 分钟(滚动删除旧段)
# 视频回放模式下默认关闭,避免边读边写同一目录
_STREAM_RECORD_DEFAULT = '0' if DISH_USE_VIDEO_FOLDER else '1'
DISH_STREAM_RECORD_ENABLED = os.environ.get(
'DISH_STREAM_RECORD_ENABLED', _STREAM_RECORD_DEFAULT,
) == '1'
DISH_STREAM_RECORD_DIR = os.environ.get('DISH_STREAM_RECORD_DIR', 'videos')
DISH_STREAM_RETENTION_MINUTES = float(os.environ.get('DISH_STREAM_RETENTION_MINUTES', '3000'))
# 单段时长(秒),默认 5 分钟一切,便于清理
DISH_STREAM_SEGMENT_SECONDS = float(os.environ.get('DISH_STREAM_SEGMENT_SECONDS', '350'))
DISH_STREAM_RECORD_FPS = float(os.environ.get('DISH_STREAM_RECORD_FPS', '10'))
DISH_STREAM_MAX_WIDTH = int(os.environ.get('DISH_STREAM_MAX_WIDTH', '1280'))
DEBUG = True
LOG_DIR = os.path.join(os.getcwd(), f'log/{time.strftime("%Y-%m-%d")}.log')
LOG_FORMAT = '<level>{level: <8}</level> <green>{time:YYYY-MM-DD HH:mm:ss.SSS}</green> - <cyan>{name}</cyan>:<cyan>{function}</cyan> - <level>{message}</level>'