Spaces:
Running
Running
Commit ·
3aab45d
1
Parent(s): a5c1536
Add some file via Upload
Browse files- Dockerfile +14 -0
- foodnutritio_baru.h5 +3 -0
- main.py +108 -0
- nutrisi_origin.csv +19 -0
- requirements.txt +90 -0
Dockerfile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
FROM python3.10
|
| 2 |
+
|
| 3 |
+
RUN useradd -m -u 1000 user
|
| 4 |
+
USER user
|
| 5 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
| 6 |
+
|
| 7 |
+
WORKDIR /app
|
| 8 |
+
|
| 9 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
| 10 |
+
RUN pip3 install --no-cache-dir --upgrade -r requirements.txt
|
| 11 |
+
|
| 12 |
+
COPY --chown=user . /app
|
| 13 |
+
CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "7860"]
|
| 14 |
+
|
foodnutritio_baru.h5
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:117f50790e45af89bb06d404853213be43a92be7d4663d65495b06521789d5bf
|
| 3 |
+
size 137447864
|
main.py
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from fastapi import FastAPI, File, UploadFile, Form
|
| 2 |
+
from pydantic import BaseModel
|
| 3 |
+
import numpy as np
|
| 4 |
+
from tensorflow.keras.models import load_model
|
| 5 |
+
import PIL.Image
|
| 6 |
+
import io
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import os
|
| 9 |
+
import gdown
|
| 10 |
+
|
| 11 |
+
url = "https://drive.google.com/drive/folders/1nXvQvjzrVDBO8-1GYQPVM5F0poIn_Dth?usp=sharing"
|
| 12 |
+
gdown.download_folder(url, output=".", quiet=True)
|
| 13 |
+
|
| 14 |
+
# Matiin log kalo run di Windows doang
|
| 15 |
+
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
|
| 16 |
+
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0'
|
| 17 |
+
|
| 18 |
+
app = FastAPI()
|
| 19 |
+
|
| 20 |
+
model = load_model("foodnutritio_baru.h5")
|
| 21 |
+
|
| 22 |
+
CLASS_NAMES = ['Ayam Bakar', 'Ayam Geprek', 'Ayam Goreng', 'Ayam Tepung', 'Bakso',
|
| 23 |
+
'Chicken Katsu', 'Donat', 'Gado-Gado', 'Kopi', 'Mie Ayam', 'Mie Instan',
|
| 24 |
+
'Nasi Goreng', 'Pecel Lele', 'Random Image', 'Rendang', 'Sate Ayam',
|
| 25 |
+
'Sop', 'Soto', 'Telur Balado']
|
| 26 |
+
|
| 27 |
+
# Muat file CSV
|
| 28 |
+
nutrisi_csv = pd.read_csv('nutrisi_origin.csv')
|
| 29 |
+
|
| 30 |
+
KOLOM_NAMA = nutrisi_csv.columns[1]
|
| 31 |
+
|
| 32 |
+
class FoodRequest(BaseModel):
|
| 33 |
+
nama_makanan: str
|
| 34 |
+
|
| 35 |
+
def get_nutrition_data(food_name: str):
|
| 36 |
+
pencarian = nutrisi_csv[nutrisi_csv[KOLOM_NAMA].str.lower() == food_name.lower()]
|
| 37 |
+
|
| 38 |
+
kalori, protein, lemak, karbo = 0.0, 0.0, 0.0, 0.0
|
| 39 |
+
kategori = "Tidak Diketahui"
|
| 40 |
+
|
| 41 |
+
if not pencarian.empty:
|
| 42 |
+
detail_nutrisi = pencarian.iloc[0]
|
| 43 |
+
|
| 44 |
+
kal_teks = str(detail_nutrisi.get('Kalori', '0')).lower().replace(',', '.').replace('g', '').strip()
|
| 45 |
+
pro_teks = str(detail_nutrisi.get('Protein', '0')).lower().replace(',', '.').replace('g', '').strip()
|
| 46 |
+
lem_teks = str(detail_nutrisi.get('Lemak', '0')).lower().replace(',', '.').replace('g', '').strip()
|
| 47 |
+
karbo_teks = str(detail_nutrisi.get('Karbohidrat', '0')).lower().replace(',', '.').replace('g', '').strip()
|
| 48 |
+
|
| 49 |
+
if 'Kategori' in detail_nutrisi:
|
| 50 |
+
kategori = str(detail_nutrisi['Kategori'])
|
| 51 |
+
|
| 52 |
+
try: kalori = float(kal_teks)
|
| 53 |
+
except: kalori = 0.0
|
| 54 |
+
|
| 55 |
+
try: protein = float(pro_teks)
|
| 56 |
+
except: protein = 0.0
|
| 57 |
+
|
| 58 |
+
try: lemak = float(lem_teks)
|
| 59 |
+
except: lemak = 0.0
|
| 60 |
+
|
| 61 |
+
try: karbo = float(karbo_teks)
|
| 62 |
+
except: karbo = 0.0
|
| 63 |
+
|
| 64 |
+
return {
|
| 65 |
+
"kalori": kalori,
|
| 66 |
+
"protein": protein,
|
| 67 |
+
"lemak": lemak,
|
| 68 |
+
"karbohidrat": karbo,
|
| 69 |
+
"kategori": kategori
|
| 70 |
+
}
|
| 71 |
+
|
| 72 |
+
@app.get('/')
|
| 73 |
+
async def hello():
|
| 74 |
+
return {"message": "Food Nutrition API Ready"}
|
| 75 |
+
|
| 76 |
+
@app.post('/predict')
|
| 77 |
+
async def predict(file: UploadFile = File(...)):
|
| 78 |
+
img_bytes = await file.read()
|
| 79 |
+
img = PIL.Image.open(io.BytesIO(img_bytes)).convert('RGB')
|
| 80 |
+
img = img.resize((128, 128))
|
| 81 |
+
|
| 82 |
+
img_array = np.array(img).astype("float32") / 255.0
|
| 83 |
+
img_array = np.expand_dims(img_array, axis=0)
|
| 84 |
+
|
| 85 |
+
preds = model.predict(img_array, verbose=0)
|
| 86 |
+
index = np.argmax(preds[0])
|
| 87 |
+
predicted_label = CLASS_NAMES[index]
|
| 88 |
+
confidence = float(np.max(preds[0]))
|
| 89 |
+
|
| 90 |
+
data_nutrisi = get_nutrition_data(predicted_label)
|
| 91 |
+
|
| 92 |
+
return {
|
| 93 |
+
"prediction": predicted_label,
|
| 94 |
+
"confidence": confidence,
|
| 95 |
+
"nutrisi": data_nutrisi
|
| 96 |
+
}
|
| 97 |
+
|
| 98 |
+
@app.post('/predict_text')
|
| 99 |
+
async def predict_text(nama_makanan: str = Form(...)):
|
| 100 |
+
|
| 101 |
+
data_nutrisi = get_nutrition_data(nama_makanan)
|
| 102 |
+
|
| 103 |
+
return {
|
| 104 |
+
"prediction": nama_makanan,
|
| 105 |
+
"confidence": 1.0,
|
| 106 |
+
"nutrisi": data_nutrisi
|
| 107 |
+
|
| 108 |
+
}
|
nutrisi_origin.csv
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
id,Nama Makanan,Kalori,Lemak,Karbohidrat,Protein,Kategori
|
| 2 |
+
M-001,Ayam Bakar,201,"11,46g",0g,"23,01g","Daging, Ayam"
|
| 3 |
+
M-002,Ayam Geprek,789,"53,97g","22,81g","52,82g","Daging, Ayam"
|
| 4 |
+
M-003,Ayam Goreng,230,12.4g,6g,23.5g,"Daging, Ayam"
|
| 5 |
+
M-004,Ayam Tepung,291,18.82g,"16,32g",15.59g,"Daging, Ayam"
|
| 6 |
+
M-005,Bakso,225,"7,87g","9,71g","27,15g",Serealia
|
| 7 |
+
M-006,Chicken Katsu,297,"18,82g","16,32g","15,59g","Daging, Ayam"
|
| 8 |
+
M-007,Donat,426,"22,9g","50,8g","5,2g",Serealia
|
| 9 |
+
M-008,Gado-gado,318,"17,86g","26,28g","17,22g",Sayur
|
| 10 |
+
M-009,Kopi,29,"0,01g","7,12g","0,19g",Minuman
|
| 11 |
+
M-010,Mie Ayam,421,"18,74g","46,21g","16,7g","Serealia, Ayam"
|
| 12 |
+
M-011,Mie Instan,350,12g,52g,8g,Serealia
|
| 13 |
+
M-012,Nasi Goreng,250,9.28g,31.38g,9.39g,Serealia
|
| 14 |
+
M-013,Pecel Lele,292,17.22g,11.9g,23.06g,Ikan
|
| 15 |
+
M-014,Rendang,468,"26,57g","10,78g","47,23g",Daging
|
| 16 |
+
M-015,Sate,101,"6,67g","2,19g","8,79g","Daging, Ayam"
|
| 17 |
+
M-015,Sop,72,"1,93g","11,98g","2,12g",Sayur
|
| 18 |
+
M-016,Soto,312,"14,92g","19,55g","24,01g",Sayur
|
| 19 |
+
M-017,Telur Balado,142,11.5g,2.44g,7.1g,Ayam
|
requirements.txt
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
absl-py==2.4.0
|
| 2 |
+
altair==6.0.0
|
| 3 |
+
annotated-doc==0.0.4
|
| 4 |
+
annotated-types==0.7.0
|
| 5 |
+
anyio==4.12.1
|
| 6 |
+
astunparse==1.6.3
|
| 7 |
+
attrs==25.4.0
|
| 8 |
+
beautifulsoup4==4.14.3
|
| 9 |
+
bleach==6.3.0
|
| 10 |
+
blinker==1.9.0
|
| 11 |
+
cachetools==6.2.6
|
| 12 |
+
certifi==2026.1.4
|
| 13 |
+
charset-normalizer==3.4.4
|
| 14 |
+
click==8.3.1
|
| 15 |
+
colorama==0.4.6
|
| 16 |
+
exceptiongroup==1.3.1
|
| 17 |
+
fastapi==0.129.0
|
| 18 |
+
filelock==3.24.3
|
| 19 |
+
Flask==3.1.2
|
| 20 |
+
flatbuffers==25.12.19
|
| 21 |
+
gast==0.7.0
|
| 22 |
+
gdown==5.2.1
|
| 23 |
+
gitdb==4.0.12
|
| 24 |
+
GitPython==3.1.46
|
| 25 |
+
google-pasta==0.2.0
|
| 26 |
+
grpcio==1.78.0
|
| 27 |
+
h11==0.16.0
|
| 28 |
+
h5py==3.15.1
|
| 29 |
+
idna==3.11
|
| 30 |
+
ImageHash==4.3.2
|
| 31 |
+
itsdangerous==2.2.0
|
| 32 |
+
Jinja2==3.1.6
|
| 33 |
+
jsonschema==4.26.0
|
| 34 |
+
jsonschema-specifications==2025.9.1
|
| 35 |
+
kaggle==1.7.4.5
|
| 36 |
+
keras==3.12.1
|
| 37 |
+
libclang==18.1.1
|
| 38 |
+
Markdown==3.10.2
|
| 39 |
+
markdown-it-py==4.0.0
|
| 40 |
+
MarkupSafe==3.0.3
|
| 41 |
+
mdurl==0.1.2
|
| 42 |
+
ml_dtypes==0.5.4
|
| 43 |
+
namex==0.1.0
|
| 44 |
+
narwhals==2.16.0
|
| 45 |
+
numpy==2.2.6
|
| 46 |
+
opt_einsum==3.4.0
|
| 47 |
+
optree==0.18.0
|
| 48 |
+
packaging==26.0
|
| 49 |
+
pandas==2.3.3
|
| 50 |
+
pillow==12.1.1
|
| 51 |
+
protobuf==6.33.5
|
| 52 |
+
pyarrow==23.0.0
|
| 53 |
+
pydantic==2.12.5
|
| 54 |
+
pydantic_core==2.41.5
|
| 55 |
+
pydeck==0.9.1
|
| 56 |
+
Pygments==2.19.2
|
| 57 |
+
PySocks==1.7.1
|
| 58 |
+
python-dateutil==2.9.0.post0
|
| 59 |
+
python-multipart==0.0.22
|
| 60 |
+
python-slugify==8.0.4
|
| 61 |
+
pytz==2025.2
|
| 62 |
+
PyWavelets==1.8.0
|
| 63 |
+
referencing==0.37.0
|
| 64 |
+
requests==2.32.5
|
| 65 |
+
rich==14.3.2
|
| 66 |
+
rpds-py==0.30.0
|
| 67 |
+
scipy==1.15.3
|
| 68 |
+
six==1.17.0
|
| 69 |
+
smmap==5.0.2
|
| 70 |
+
soupsieve==2.8.3
|
| 71 |
+
starlette==0.52.1
|
| 72 |
+
streamlit==1.54.0
|
| 73 |
+
tenacity==9.1.4
|
| 74 |
+
tensorboard==2.20.0
|
| 75 |
+
tensorboard-data-server==0.7.2
|
| 76 |
+
tensorflow==2.20.0
|
| 77 |
+
termcolor==3.3.0
|
| 78 |
+
text-unidecode==1.3
|
| 79 |
+
toml==0.10.2
|
| 80 |
+
tornado==6.5.4
|
| 81 |
+
tqdm==4.67.3
|
| 82 |
+
typing-inspection==0.4.2
|
| 83 |
+
typing_extensions==4.15.0
|
| 84 |
+
tzdata==2025.3
|
| 85 |
+
urllib3==2.6.3
|
| 86 |
+
uvicorn==0.41.0
|
| 87 |
+
watchdog==6.0.0
|
| 88 |
+
webencodings==0.5.1
|
| 89 |
+
Werkzeug==3.1.5
|
| 90 |
+
wrapt==2.1.1
|