74 lines
2.2 KiB
Python
74 lines
2.2 KiB
Python
# coding=utf-8
|
||
"""识别结果 vs 当天排餐:不在菜单中的已识别菜 → 待学习库人工确认。"""
|
||
import os
|
||
|
||
|
||
def flag_dishes_not_in_menu(manager, dishes, meal_store=None):
|
||
"""
|
||
对「已识别且不在今日排餐」的菜写入待学习库。
|
||
返回被标记的 pending_id 列表。
|
||
"""
|
||
if meal_store is None:
|
||
from dao.meal_schedule import get_meal_schedule_store
|
||
meal_store = get_meal_schedule_store()
|
||
|
||
menu = meal_store.today_dish_names()
|
||
if not menu:
|
||
# 当天无排餐数据时不做比对,避免把全部菜打进待学习
|
||
return []
|
||
|
||
try:
|
||
from dao.settings import DISH_STAPLE_NAMES
|
||
staples = set(DISH_STAPLE_NAMES or [])
|
||
except Exception:
|
||
staples = set()
|
||
|
||
pending_ids = []
|
||
extract = getattr(manager, '_extract_image_feature', None)
|
||
store = getattr(manager, 'pending_store', None)
|
||
if store is None or extract is None:
|
||
return []
|
||
|
||
for d in dishes or []:
|
||
if d.get('is_unknown'):
|
||
continue
|
||
if d.get('match_scope') == 'staple':
|
||
continue
|
||
name = (d.get('label') or d.get('name') or '').strip()
|
||
if not name:
|
||
continue
|
||
if name in menu or name in staples:
|
||
continue
|
||
|
||
crop = d.get('crop_image')
|
||
if not crop or not os.path.isfile(str(crop)):
|
||
continue
|
||
|
||
try:
|
||
feat = extract(crop)
|
||
except Exception as exc:
|
||
print(f'[WARN] schedule-check feature failed: {exc}')
|
||
continue
|
||
if feat is None:
|
||
continue
|
||
|
||
reason = f'不在今日排餐(识别为:{name})'
|
||
try:
|
||
pid = store.add(
|
||
crop,
|
||
feat,
|
||
suggested_category=name,
|
||
score=d.get('score'),
|
||
reason=reason,
|
||
)
|
||
except TypeError:
|
||
# 兼容旧版 add 无 reason 参数
|
||
pid = store.add(crop, feat, suggested_category=name, score=d.get('score'))
|
||
if pid:
|
||
d['pending_id'] = pid
|
||
d['schedule_mismatch'] = True
|
||
pending_ids.append(pid)
|
||
print(f'[INFO] schedule mismatch -> pending#{pid}: {name}')
|
||
|
||
return pending_ids
|