BlasterBlade65 commited on
Commit
9a7d30f
·
0 Parent(s):

upload fruit captioning ai

Browse files
.gitattributes ADDED
@@ -0,0 +1,2 @@
 
 
 
1
+ *.h5 filter=lfs diff=lfs merge=lfs -text
2
+ *.pkl filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,187 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import streamlit as st
2
+ import numpy as np
3
+ import pickle
4
+ import tensorflow as tf
5
+ import os
6
+ import pandas as pd
7
+ from datetime import datetime
8
+ from tensorflow.keras.models import load_model
9
+ from tensorflow.keras.preprocessing.sequence import pad_sequences
10
+ from tensorflow.keras.applications.mobilenet_v2 import MobileNetV2, preprocess_input
11
+ from tensorflow.keras.preprocessing.image import img_to_array
12
+ from PIL import Image
13
+
14
+ # ==========================================
15
+ # 1. KONFIGURASI PATH (DINAMIS)
16
+ # ==========================================
17
+ # BASE_DIR mengarah ke folder tempat file .py ini berada
18
+ BASE_DIR = os.path.dirname(os.path.abspath(__file__))
19
+ MODEL_DIR = os.path.join(BASE_DIR, 'models')
20
+
21
+ # Path file di dalam folder models
22
+ PATH_MODEL_CAPTION = os.path.join(MODEL_DIR, 'fruit_caption_model.h5')
23
+ PATH_TOKENIZER = os.path.join(MODEL_DIR, 'tokenizer.pkl')
24
+ PATH_GRAFIK = os.path.join(MODEL_DIR, '1_grafik_akurasi.png')
25
+ PATH_LOG = os.path.join(MODEL_DIR, 'riwayat_penggunaan.csv')
26
+
27
+ # ==========================================
28
+ # 2. TAMPILAN UI UTAMA
29
+ # ==========================================
30
+ st.set_page_config(page_title="AI Fruit Captioning", page_icon="🥭", layout="wide")
31
+
32
+ st.title("🍎 Identifikasi Citra Buah Menggunakan Image Captioning")
33
+ st.write("Sistem otomatis yang mendeskripsikan jenis buah, kandungan vitamin, dan manfaatnya menggunakan Deep Learning.")
34
+
35
+ # ==========================================
36
+ # 3. FUNGSI LOGIKA SISTEM
37
+ # ==========================================
38
+
39
+ def save_to_log(nama, vitamin, deskripsi):
40
+ """Menyimpan hasil identifikasi ke file CSV internal."""
41
+ now = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
42
+ new_data = {
43
+ 'Waktu': [now],
44
+ 'Nama Buah': [nama],
45
+ 'Vitamin': [vitamin],
46
+ 'Deskripsi': [deskripsi]
47
+ }
48
+ df_new = pd.DataFrame(new_data)
49
+
50
+ if not os.path.exists(MODEL_DIR):
51
+ os.makedirs(MODEL_DIR)
52
+
53
+ if not os.path.isfile(PATH_LOG):
54
+ df_new.to_csv(PATH_LOG, index=False)
55
+ else:
56
+ df_new.to_csv(PATH_LOG, mode='a', header=False, index=False)
57
+
58
+ @st.cache_resource
59
+ def load_assets():
60
+ """Memuat model dan tokenizer sekali saja (caching)."""
61
+ if not os.path.exists(PATH_MODEL_CAPTION) or not os.path.exists(PATH_TOKENIZER):
62
+ raise FileNotFoundError("File model atau tokenizer tidak ditemukan di folder 'models'!")
63
+
64
+ model = load_model(PATH_MODEL_CAPTION)
65
+ with open(PATH_TOKENIZER, 'rb') as f:
66
+ tokenizer = pickle.load(f)
67
+
68
+ # Encoder: MobileNetV2
69
+ base_model = MobileNetV2(weights='imagenet')
70
+ fe_model = tf.keras.Model(inputs=base_model.inputs, outputs=base_model.layers[-2].output)
71
+
72
+ return model, tokenizer, fe_model
73
+
74
+ def generate_caption(image, model, tokenizer, fe_model):
75
+ """Proses ekstraksi fitur dan pembuatan teks deskripsi."""
76
+ img = image.convert('RGB')
77
+ img = img.resize((224, 224))
78
+ img = img_to_array(img)
79
+ img = np.expand_dims(img, axis=0)
80
+ img = preprocess_input(img)
81
+
82
+ # Ekstraksi Fitur (CNN)
83
+ feature = fe_model.predict(img, verbose=0)
84
+
85
+ # Generate Teks (LSTM)
86
+ max_length = 21
87
+ in_text = 'startseq'
88
+
89
+ for i in range(max_length):
90
+ sequence = tokenizer.texts_to_sequences([in_text])[0]
91
+ sequence = pad_sequences([sequence], maxlen=max_length)
92
+ yhat = model.predict([feature, sequence], verbose=0)
93
+ idx = np.argmax(yhat)
94
+ word = tokenizer.index_word.get(idx)
95
+ if word is None or word == 'endseq':
96
+ break
97
+ in_text += ' ' + word
98
+
99
+ return in_text.replace('startseq', '').strip()
100
+
101
+ # ==========================================
102
+ # 4. ALUR PROSES APLIKASI
103
+ # ==========================================
104
+
105
+ # Memuat Aset
106
+ try:
107
+ model, tokenizer, fe_model = load_assets()
108
+ except Exception as e:
109
+ st.error(f"⚠️ Gagal memuat sistem: {e}")
110
+ st.stop()
111
+
112
+ # Input Gambar
113
+ uploaded_file = st.file_uploader("Unggah foto buah (JPG/PNG/JPEG)", type=["jpg", "png", "jpeg"])
114
+
115
+ if uploaded_file is not None:
116
+ img_display = Image.open(uploaded_file).convert('RGB')
117
+
118
+ col1, col2 = st.columns([1, 1])
119
+
120
+ with col1:
121
+ st.subheader("🖼️ Citra Input")
122
+ st.image(img_display, use_container_width=True)
123
+
124
+ with col2:
125
+ st.subheader("🤖 Hasil Analisis AI")
126
+ with st.spinner('Menganalisis citra...'):
127
+ try:
128
+ caption = generate_caption(img_display, model, tokenizer, fe_model)
129
+
130
+ # Parsing teks (asumsi output: "buah [nama] deskripsi [teks] mengandung vitamin [vit]")
131
+ if ' deskripsi ' in caption and ' mengandung vitamin ' in caption:
132
+ parts = caption.split(' deskripsi ')
133
+ nama_buah = parts[0].replace('buah ', '').title()
134
+ detail = parts[1].split(' mengandung vitamin ')
135
+ deskripsi_clean = detail[0].capitalize()
136
+ vitamin_clean = detail[1]
137
+
138
+ # Tampilan Hasil ke User
139
+ st.success(f"**Jenis Buah:** {nama_buah}")
140
+ st.metric(label="Kandungan Utama", value=f"Vitamin {vitamin_clean}")
141
+ st.info(f"**Keterangan:**\n{deskripsi_clean}")
142
+
143
+ # Simpan ke Log Internal
144
+ save_to_log(nama_buah, vitamin_clean, deskripsi_clean)
145
+ st.toast("Data riwayat telah diperbarui!", icon="✅")
146
+ else:
147
+ st.warning("Model memberikan output yang tidak standar:")
148
+ st.write(f"_{caption}_")
149
+
150
+ except Exception as e:
151
+ st.error(f"Terjadi kesalahan saat klasifikasi: {e}")
152
+
153
+ # ==========================================
154
+ # 5. SIDEBAR (METODOLOGI & DOWNLOAD USER)
155
+ # ==========================================
156
+ with st.sidebar:
157
+ st.header("📊 Informasi & Riwayat")
158
+
159
+ # Visualisasi Akurasi (Jika ada)
160
+ if os.path.exists(PATH_GRAFIK):
161
+ st.image(PATH_GRAFIK, caption="Grafik Performa Model", use_container_width=True)
162
+
163
+ st.markdown("---")
164
+ st.subheader("📥 Download Riwayat")
165
+ st.write("Unduh hasil identifikasi Anda untuk keperluan laporan.")
166
+
167
+ if os.path.exists(PATH_LOG):
168
+ df_log = pd.read_csv(PATH_LOG)
169
+
170
+ # Tombol Download untuk User
171
+ csv_data = df_log.to_csv(index=False).encode('utf-8')
172
+ st.download_button(
173
+ label="Download File CSV",
174
+ data=csv_data,
175
+ file_name=f"riwayat_identifikasi_{datetime.now().strftime('%Y%m%d')}.csv",
176
+ mime="text/csv",
177
+ use_container_width=True
178
+ )
179
+
180
+ # Tampilkan tabel singkat di sidebar
181
+ st.write("**5 Data Terakhir:**")
182
+ st.dataframe(df_log.tail(5), use_container_width=True)
183
+ else:
184
+ st.info("Belum ada data riwayat.")
185
+
186
+ st.markdown("---")
187
+ st.caption("Teknologi: MobileNetV2 (CNN) + Long Short-Term Memory (LSTM)")
models/features.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:beffdd103295c08ce723dd1e240cb2443bdde81b72ac2123f2d0694e815a00c0
3
+ size 679294718
models/fruit_classifier_model.h5 ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:d8578b3c70f485e1e9287a40f03b48ed3065c419e0a7c3575d112d1cb36ab34e
3
+ size 80666868
models/tokenizer.pkl ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:7e851bbcacf8e207484284a2b7cd83df920d3e06ea203ead6c2ecc1d7f7052af
3
+ size 11819
requirements.txt ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ tensorflow
2
+ numpy
3
+ pillow
4
+ scikit-learn
5
+ pickle-mixin
6
+ gradio