Spaces:
Running
Running
Download main.py from EasyWinter/FoodNutritionAPI: direct link, hf CLI and curl.
- Browser
- Download file 3.44 kB
-
https://huggingface.co/spaces/EasyWinter/FoodNutritionAPI/resolve/main/main.py
- Command line
-
hf download hf://spaces/EasyWinter/FoodNutritionAPI/main.py
-
curl -L -o main.py https://huggingface.co/spaces/EasyWinter/FoodNutritionAPI/resolve/main/main.py
3.44 kB
| from fastapi import FastAPI, File, UploadFile, Form | |
| from pydantic import BaseModel | |
| import numpy as np | |
| from tensorflow.keras.models import load_model | |
| import PIL.Image | |
| import io | |
| import pandas as pd | |
| import os | |
| app = FastAPI() | |
| model = load_model("foodnutrition.keras", compile=False) | |
| CLASS_NAMES = [ | |
| 'Ayam Bakar', 'Ayam Geprek', 'Ayam Goreng', 'Ayam Tepung', 'Bakso', 'Bakwan', | |
| 'Batagor', 'Bolu Kukus', 'Burger', 'Cap Cay', 'Chicken Katsu', 'Cilok', | |
| 'Dimsum', 'Donat', 'Es Teh', 'Gado-Gado', 'Ikan Goreng', 'Jasuke', | |
| 'Jus Jeruk', 'Kikil', 'Kopi', 'Krepes', 'Lemper', 'Mie Ayam', | |
| 'Mie Instan', 'Nasi Goreng', 'Nasi Padang', 'Pecel Lele', 'Pizza', | |
| 'Random Image', 'Rendang', 'Risoles', 'Sate Ayam', 'Seblak', | |
| 'Siomay', 'Sop', 'Soto', 'Tahu', 'Tangkil', 'Telur Balado', | |
| 'Telur Dadar', 'Tempe', 'Thai Tea' | |
| ] | |
| # Muat file CSV | |
| nutrisi_csv = pd.read_csv('nutrisi_origin.csv') | |
| KOLOM_NAMA = nutrisi_csv.columns[1] | |
| class FoodRequest(BaseModel): | |
| nama_makanan: str | |
| def get_nutrition_data(food_name: str): | |
| pencarian = nutrisi_csv[nutrisi_csv[KOLOM_NAMA].str.lower() == food_name.lower()] | |
| kalori, protein, lemak, karbo = 0.0, 0.0, 0.0, 0.0 | |
| kategori = "Tidak Diketahui" | |
| if not pencarian.empty: | |
| detail_nutrisi = pencarian.iloc[0] | |
| kal_teks = str(detail_nutrisi.get('Kalori', '0')).lower().replace(',', '.').replace('g', '').strip() | |
| pro_teks = str(detail_nutrisi.get('Protein', '0')).lower().replace(',', '.').replace('g', '').strip() | |
| lem_teks = str(detail_nutrisi.get('Lemak', '0')).lower().replace(',', '.').replace('g', '').strip() | |
| karbo_teks = str(detail_nutrisi.get('Karbohidrat', '0')).lower().replace(',', '.').replace('g', '').strip() | |
| if 'Kategori' in detail_nutrisi: | |
| kategori = str(detail_nutrisi['Kategori']) | |
| try: kalori = float(kal_teks) | |
| except: kalori = 0.0 | |
| try: protein = float(pro_teks) | |
| except: protein = 0.0 | |
| try: lemak = float(lem_teks) | |
| except: lemak = 0.0 | |
| try: karbo = float(karbo_teks) | |
| except: karbo = 0.0 | |
| return { | |
| "kalori": kalori, | |
| "protein": protein, | |
| "lemak": lemak, | |
| "karbohidrat": karbo, | |
| "kategori": kategori | |
| } | |
| async def hello(): | |
| return {"message": "Food Nutrition API Ready"} | |
| async def predict(file: UploadFile = File(...)): | |
| img_bytes = await file.read() | |
| img = PIL.Image.open(io.BytesIO(img_bytes)).convert('RGB') | |
| img = img.resize((244, 244)) | |
| img_array = np.array(img).astype("float32") / 255.0 | |
| img_array = np.expand_dims(img_array, axis=0) | |
| preds = model.predict(img_array, verbose=0) | |
| index = np.argmax(preds[0]) | |
| confidence = round(float(np.max(preds[0])) * 100, 2) | |
| if confidence >= 90.0: | |
| predicted_label = CLASS_NAMES[index] | |
| else: | |
| predicted_label = "Tidak diketahui" | |
| probability = [] | |
| for i, prob in enumerate(preds[0]): | |
| probability.append({ | |
| "label": CLASS_NAMES[i], | |
| "score": round(float(prob) * 100, 2) | |
| }) | |
| probability = sorted(probability, key=lambda x: x["score"], reverse=True) | |
| data_nutrisi = get_nutrition_data(predicted_label) | |
| return { | |
| "prediction": predicted_label, | |
| "confidence": confidence, | |
| "probability": probability, | |
| "nutrisi": data_nutrisi | |
| } |