Chao-Ying commited on
Commit
90b796c
·
verified ·
1 Parent(s): f1615f0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -9
app.py CHANGED
@@ -103,6 +103,8 @@ FOOD_DB = {
103
  "egg": {"kcal":155,"carb_g":1.1,"protein_g":13, "fat_g":11, "sodium_mg":124, "cat":"豆魚蛋肉類", "base_g":60, "tip":"水煮/荷包少油,避免重鹹醬料"},
104
  "banana":{"kcal":89, "carb_g":23, "protein_g":1.1,"fat_g":0.3,"sodium_mg":1, "cat":"水果類", "base_g":100, "tip":"控制份量,避免一次過量"},
105
  "miso_soup":{"kcal":36,"carb_g":4.3,"protein_g":2.0,"fat_g":1.3,"sodium_mg":550, "cat":"湯品/飲品", "base_g":200, "tip":"味噌湯偏鹹,建議少量品嚐"},
 
 
106
  }
107
 
108
  ALIASES = {
@@ -137,22 +139,69 @@ def detect_foods_from_text(text: str) -> List[str]:
137
  import re
138
  DEFAULT_BASE_G = 100
139
  STOPWORDS = {
 
140
  "a","an","the","with","and","of","on","in","to","served","over","side","sides",
141
- "plate","bento","box","set","dish","meal","mixed","assorted","fresh","hot","cold",
142
- "grilled","roasted","fried","deep","steamed","boiled","braised","stir","stirred","sautéed",
143
- "sauce","soup","salad","topped","seasoned","style","japanese","taiwanese","korean","chinese",
144
  "便當","套餐","一盤","一碗","配菜","附餐","湯","沙拉","醬","佐","搭配","附","拌","炒","滷","炸","烤","蒸","煮"
145
  }
 
 
 
 
 
 
 
 
 
 
 
 
146
  def extract_food_terms_free(text: str):
147
- parts = re.split(r"(?:,|\.|;|\band\b|\bwith\b|\bserved with\b|\baccompanied by\b|\n)+", text, flags=re.I)
 
 
 
 
 
 
 
148
  hits = set()
 
 
 
 
 
 
 
 
 
 
 
149
  for p in parts:
150
- if not p: continue
151
- toks = re.findall(r"[A-Za-z\u4e00-\u9fff]+", p.lower())
152
- toks = [w for w in toks if len(w) >= 2 and w not in STOPWORDS]
153
- if not toks: continue
154
- head = toks[-1]
 
 
 
 
 
 
 
 
 
 
 
155
  hits.add(ALIASES.get(head, head))
 
 
 
 
 
 
156
  return list(hits)
157
 
158
  def estimate_weight(name: str, plate_cm: int, portion: str) -> int:
 
103
  "egg": {"kcal":155,"carb_g":1.1,"protein_g":13, "fat_g":11, "sodium_mg":124, "cat":"豆魚蛋肉類", "base_g":60, "tip":"水煮/荷包少油,避免重鹹醬料"},
104
  "banana":{"kcal":89, "carb_g":23, "protein_g":1.1,"fat_g":0.3,"sodium_mg":1, "cat":"水果類", "base_g":100, "tip":"控制份量,避免一次過量"},
105
  "miso_soup":{"kcal":36,"carb_g":4.3,"protein_g":2.0,"fat_g":1.3,"sodium_mg":550, "cat":"湯品/飲品", "base_g":200, "tip":"味噌湯偏鹹,建議少量品嚐"},
106
+ "salad": {"kcal":30,"carb_g":5,"protein_g":1.5,"fat_g":0.5,"sodium_mg":40,"cat":"蔬菜類","base_g":100,"tip":"少醬少油,優先清爽調味"},
107
+ "fish": {"kcal":170,"carb_g":0,"protein_g":22,"fat_g":8,"sodium_mg":70,"cat":"豆魚蛋肉類","base_g":120,"tip":"蒸/烤/煎少油,避免重鹹醬汁"},
108
  }
109
 
110
  ALIASES = {
 
139
  import re
140
  DEFAULT_BASE_G = 100
141
  STOPWORDS = {
142
+ # 英文
143
  "a","an","the","with","and","of","on","in","to","served","over","side","sides",
144
+ "set","dish","meal","mixed","assorted","fresh","hot","cold","topped","style","seasoned",
145
+ # 中文
 
146
  "便當","套餐","一盤","一碗","配菜","附餐","湯","沙拉","醬","佐","搭配","附","拌","炒","滷","炸","烤","蒸","煮"
147
  }
148
+ COLOR_WORDS = {"white","black","red","green","yellow","orange","brown","purple","pink","golden"}
149
+ UTENSILS = {"plate","bowl","tray","box","cup","glass","plateful","bento"}
150
+ ADJ_MISC = {"piece","slice","fillet","serving","topped","mixed","assorted"}
151
+
152
+ # 常見食物名詞(沒有就先列為候選)
153
+ FOOD_LIKE = {
154
+ "salad","fish","chicken","beef","pork","shrimp","tofu","egg",
155
+ "rice","noodles","bread","soup","vegetables","veggies","fruit"
156
+ }
157
+
158
+ import re
159
+
160
  def extract_food_terms_free(text: str):
161
+ """
162
+ 從 caption 中抽食物詞(允許未知):
163
+ - 解析片語:piece/slice/fillet/serving of X → X
164
+ - 切片(逗號/and/with),去掉顏色、器皿、形容詞停用詞
165
+ - 取片尾名詞;若無,掃描整句抓常見食物名詞
166
+ - Alias → 主鍵;沒對到就保留原字(當未知)
167
+ """
168
+ t = text.strip().lower()
169
  hits = set()
170
+
171
+ # 1) 特例:「X of Y」→ 直接抓 Y
172
+ for pat in [r"(?:piece|slice|fillet|serving)\s+of\s+([a-z\u4e00-\u9fff]+)"]:
173
+ for m in re.findall(pat, t, flags=re.I):
174
+ y = m.strip()
175
+ if y in COLOR_WORDS or y in UTENSILS or y in ADJ_MISC or y in STOPWORDS:
176
+ continue
177
+ hits.add(ALIASES.get(y, y))
178
+
179
+ # 2) 片段切分(逗號、分號、and、with、換行)
180
+ parts = re.split(r"(?:,|;|\.|\band\b|\bwith\b|\n)+", t, flags=re.I)
181
  for p in parts:
182
+ if not p:
183
+ continue
184
+ # 擷取英/中文字
185
+ toks = re.findall(r"[a-z\u4e00-\u9fff]+", p)
186
+ # 過濾顏色/器皿/形容詞/停用詞
187
+ toks = [
188
+ w for w in toks
189
+ if w not in COLOR_WORDS
190
+ and w not in UTENSILS
191
+ and w not in ADJ_MISC
192
+ and w not in STOPWORDS
193
+ and len(w) >= 2
194
+ ]
195
+ if not toks:
196
+ continue
197
+ head = toks[-1] # 片尾通常是名詞,如 "salad"/"fish"
198
  hits.add(ALIASES.get(head, head))
199
+
200
+ # 3) 萬一片段沒抓到,再從整句補常見食物名詞
201
+ for w in FOOD_LIKE:
202
+ if re.search(rf"\b{re.escape(w)}\b", t):
203
+ hits.add(ALIASES.get(w, w))
204
+
205
  return list(hits)
206
 
207
  def estimate_weight(name: str, plate_cm: int, portion: str) -> int: