yuting111222 commited on
Commit
cb8b92c
·
1 Parent(s): b938416

deploy: 推送到 Hugging Face Spaces

Browse files
Files changed (2) hide show
  1. food_analyzer.py +12 -29
  2. services/meal_service.py +23 -25
food_analyzer.py CHANGED
@@ -3,10 +3,10 @@ from fastapi.middleware.cors import CORSMiddleware
3
  from PIL import Image
4
  import io
5
  import base64
6
- from transformers import pipeline
7
  import requests
8
  import json
9
- from typing import Dict, Any
10
  from pydantic import BaseModel
11
  import uvicorn
12
 
@@ -245,33 +245,26 @@ async def analyze_food(file: UploadFile = File(...)):
245
  # 檢查模型是否載入成功
246
  if not food_classifier:
247
  raise HTTPException(status_code=500, detail="AI模型尚未載入,請稍後再試")
248
-
249
  # 檢查文件類型
250
- if not file.content_type.startswith("image/"):
251
  raise HTTPException(status_code=400, detail="請上傳圖片文件")
252
-
253
  # 讀取圖片
254
  image_data = await file.read()
255
  image = Image.open(io.BytesIO(image_data))
256
-
257
  # 確保圖片是RGB格式
258
  if image.mode != "RGB":
259
  image = image.convert("RGB")
260
-
261
  # 使用AI模型進行食物辨識
262
  results = food_classifier(image)
263
-
264
- # 獲取最高信心度的結果
265
  top_result = results[0]
266
- food_name = top_result["label"]
267
- confidence = top_result["score"]
268
-
269
  # 獲取營養資訊
270
  nutrition_info = get_nutrition_info(food_name)
271
-
272
  # 生成AI建議
273
  ai_suggestions = generate_ai_suggestions(food_name, nutrition_info)
274
-
275
  return FoodAnalysisResponse(
276
  success=True,
277
  food_name=food_name,
@@ -280,7 +273,6 @@ async def analyze_food(file: UploadFile = File(...)):
280
  ai_suggestions=ai_suggestions,
281
  message="食物分析完成"
282
  )
283
-
284
  except Exception as e:
285
  raise HTTPException(status_code=500, detail=f"分析失敗: {str(e)}")
286
 
@@ -291,38 +283,30 @@ async def analyze_food_base64(image_data: dict):
291
  # 檢查模型是否載入成功
292
  if not food_classifier:
293
  raise HTTPException(status_code=500, detail="AI模型尚未載入,請稍後再試")
294
-
295
  # 解碼base64圖片
296
  base64_string = image_data.get("image", "")
297
  if not base64_string:
298
  raise HTTPException(status_code=400, detail="缺少圖片資料")
299
-
300
  # 移除base64前綴(如果有的話)
301
  if "," in base64_string:
302
- base64_string = base64_string.split(",")[1]
303
-
304
  # 解碼圖片
305
  image_bytes = base64.b64decode(base64_string)
306
  image = Image.open(io.BytesIO(image_bytes))
307
-
308
  # 確保圖片是RGB格式
309
  if image.mode != "RGB":
310
  image = image.convert("RGB")
311
-
312
  # 使用AI模型進行食物辨識
313
  results = food_classifier(image)
314
-
315
- # 獲取最高信心度的結果
316
  top_result = results[0]
317
- food_name = top_result["label"]
318
- confidence = top_result["score"]
319
-
320
  # 獲取營養資訊
321
  nutrition_info = get_nutrition_info(food_name)
322
-
323
  # 生成AI建議
324
  ai_suggestions = generate_ai_suggestions(food_name, nutrition_info)
325
-
326
  return FoodAnalysisResponse(
327
  success=True,
328
  food_name=food_name,
@@ -331,7 +315,6 @@ async def analyze_food_base64(image_data: dict):
331
  ai_suggestions=ai_suggestions,
332
  message="食物分析完成"
333
  )
334
-
335
  except Exception as e:
336
  raise HTTPException(status_code=500, detail=f"分析失敗: {str(e)}")
337
 
 
3
  from PIL import Image
4
  import io
5
  import base64
6
+ from transformers.pipelines import pipeline # 修正匯入
7
  import requests
8
  import json
9
+ from typing import Dict, Any, List, Optional
10
  from pydantic import BaseModel
11
  import uvicorn
12
 
 
245
  # 檢查模型是否載入成功
246
  if not food_classifier:
247
  raise HTTPException(status_code=500, detail="AI模型尚未載入,請稍後再試")
 
248
  # 檢查文件類型
249
+ if not file.content_type or not file.content_type.startswith("image/"):
250
  raise HTTPException(status_code=400, detail="請上傳圖片文件")
 
251
  # 讀取圖片
252
  image_data = await file.read()
253
  image = Image.open(io.BytesIO(image_data))
 
254
  # 確保圖片是RGB格式
255
  if image.mode != "RGB":
256
  image = image.convert("RGB")
 
257
  # 使用AI模型進行食物辨識
258
  results = food_classifier(image)
259
+ if not isinstance(results, list) or not results:
260
+ raise HTTPException(status_code=500, detail="AI模型辨識失敗")
261
  top_result = results[0]
262
+ food_name = str(top_result.get("label", "Unknown"))
263
+ confidence = float(top_result.get("score", 0.0))
 
264
  # 獲取營養資訊
265
  nutrition_info = get_nutrition_info(food_name)
 
266
  # 生成AI建議
267
  ai_suggestions = generate_ai_suggestions(food_name, nutrition_info)
 
268
  return FoodAnalysisResponse(
269
  success=True,
270
  food_name=food_name,
 
273
  ai_suggestions=ai_suggestions,
274
  message="食物分析完成"
275
  )
 
276
  except Exception as e:
277
  raise HTTPException(status_code=500, detail=f"分析失敗: {str(e)}")
278
 
 
283
  # 檢查模型是否載入成功
284
  if not food_classifier:
285
  raise HTTPException(status_code=500, detail="AI模型尚未載入,請稍後再試")
 
286
  # 解碼base64圖片
287
  base64_string = image_data.get("image", "")
288
  if not base64_string:
289
  raise HTTPException(status_code=400, detail="缺少圖片資料")
 
290
  # 移除base64前綴(如果有的話)
291
  if "," in base64_string:
292
+ base64_string = base64_string.split(",", 1)[1]
 
293
  # 解碼圖片
294
  image_bytes = base64.b64decode(base64_string)
295
  image = Image.open(io.BytesIO(image_bytes))
 
296
  # 確保圖片是RGB格式
297
  if image.mode != "RGB":
298
  image = image.convert("RGB")
 
299
  # 使用AI模型進行食物辨識
300
  results = food_classifier(image)
301
+ if not isinstance(results, list) or not results:
302
+ raise HTTPException(status_code=500, detail="AI模型辨識失敗")
303
  top_result = results[0]
304
+ food_name = str(top_result.get("label", "Unknown"))
305
+ confidence = float(top_result.get("score", 0.0))
 
306
  # 獲取營養資訊
307
  nutrition_info = get_nutrition_info(food_name)
 
308
  # 生成AI建議
309
  ai_suggestions = generate_ai_suggestions(food_name, nutrition_info)
 
310
  return FoodAnalysisResponse(
311
  success=True,
312
  food_name=food_name,
 
315
  ai_suggestions=ai_suggestions,
316
  message="食物分析完成"
317
  )
 
318
  except Exception as e:
319
  raise HTTPException(status_code=500, detail=f"分析失敗: {str(e)}")
320
 
services/meal_service.py CHANGED
@@ -22,17 +22,16 @@ class MealService:
22
  food_name=food_name,
23
  meal_type=meal_type,
24
  portion_size=portion_size,
25
- calories=nutrition.get('calories', 0),
26
- protein=nutrition.get('protein', 0),
27
- carbs=nutrition.get('carbs', 0),
28
- fat=nutrition.get('fat', 0),
29
- fiber=nutrition.get('fiber', 0),
30
  meal_date=meal_date,
31
  image_url=image_url,
32
  ai_analysis=ai_analysis,
33
  created_at=datetime.utcnow()
34
  )
35
-
36
  self.db.add(meal_log)
37
  self.db.commit()
38
  self.db.refresh(meal_log)
@@ -46,14 +45,12 @@ class MealService:
46
  ) -> List[MealLog]:
47
  """獲取用餐記錄"""
48
  query = self.db.query(MealLog)
49
-
50
  if start_date:
51
  query = query.filter(MealLog.meal_date >= start_date)
52
  if end_date:
53
  query = query.filter(MealLog.meal_date <= end_date)
54
  if meal_type:
55
  query = query.filter(MealLog.meal_type == meal_type)
56
-
57
  return query.order_by(MealLog.meal_date.desc()).all()
58
 
59
  def get_nutrition_summary(
@@ -63,27 +60,28 @@ class MealService:
63
  ) -> Dict[str, float]:
64
  """獲取指定時間範圍內的營養攝入總結"""
65
  meals = self.get_meal_logs(start_date, end_date)
66
-
67
- summary = {
68
- 'total_calories': 0,
69
- 'total_protein': 0,
70
- 'total_carbs': 0,
71
- 'total_fat': 0,
72
- 'total_fiber': 0
73
  }
74
-
75
  for meal in meals:
76
- # 根據份量大小調整營養值
 
 
 
 
 
77
  multiplier = {
78
  'small': 0.7,
79
  'medium': 1.0,
80
  'large': 1.3
81
- }.get(meal.portion_size, 1.0)
82
-
83
- summary['total_calories'] += meal.calories * multiplier
84
- summary['total_protein'] += meal.protein * multiplier
85
- summary['total_carbs'] += meal.carbs * multiplier
86
- summary['total_fat'] += meal.fat * multiplier
87
- summary['total_fiber'] += meal.fiber * multiplier
88
-
89
  return summary
 
22
  food_name=food_name,
23
  meal_type=meal_type,
24
  portion_size=portion_size,
25
+ calories=float(nutrition.get('calories', 0)),
26
+ protein=float(nutrition.get('protein', 0)),
27
+ carbs=float(nutrition.get('carbs', 0)),
28
+ fat=float(nutrition.get('fat', 0)),
29
+ fiber=float(nutrition.get('fiber', 0)),
30
  meal_date=meal_date,
31
  image_url=image_url,
32
  ai_analysis=ai_analysis,
33
  created_at=datetime.utcnow()
34
  )
 
35
  self.db.add(meal_log)
36
  self.db.commit()
37
  self.db.refresh(meal_log)
 
45
  ) -> List[MealLog]:
46
  """獲取用餐記錄"""
47
  query = self.db.query(MealLog)
 
48
  if start_date:
49
  query = query.filter(MealLog.meal_date >= start_date)
50
  if end_date:
51
  query = query.filter(MealLog.meal_date <= end_date)
52
  if meal_type:
53
  query = query.filter(MealLog.meal_type == meal_type)
 
54
  return query.order_by(MealLog.meal_date.desc()).all()
55
 
56
  def get_nutrition_summary(
 
60
  ) -> Dict[str, float]:
61
  """獲取指定時間範圍內的營養攝入總結"""
62
  meals = self.get_meal_logs(start_date, end_date)
63
+ summary: Dict[str, float] = {
64
+ 'total_calories': 0.0,
65
+ 'total_protein': 0.0,
66
+ 'total_carbs': 0.0,
67
+ 'total_fat': 0.0,
68
+ 'total_fiber': 0.0
 
69
  }
 
70
  for meal in meals:
71
+ portion_size = getattr(meal, 'portion_size', 'medium')
72
+ calories = getattr(meal, 'calories', 0.0)
73
+ protein = getattr(meal, 'protein', 0.0)
74
+ carbs = getattr(meal, 'carbs', 0.0)
75
+ fat = getattr(meal, 'fat', 0.0)
76
+ fiber = getattr(meal, 'fiber', 0.0)
77
  multiplier = {
78
  'small': 0.7,
79
  'medium': 1.0,
80
  'large': 1.3
81
+ }.get(portion_size, 1.0)
82
+ summary['total_calories'] += float(calories) * multiplier
83
+ summary['total_protein'] += float(protein) * multiplier
84
+ summary['total_carbs'] += float(carbs) * multiplier
85
+ summary['total_fat'] += float(fat) * multiplier
86
+ summary['total_fiber'] += float(fiber) * multiplier
 
 
87
  return summary