EasyWinter commited on
Commit
3aab45d
·
1 Parent(s): a5c1536

Add some file via Upload

Browse files
Files changed (5) hide show
  1. Dockerfile +14 -0
  2. foodnutritio_baru.h5 +3 -0
  3. main.py +108 -0
  4. nutrisi_origin.csv +19 -0
  5. 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