DimasMP3 commited on
Commit
a722bd4
·
0 Parent(s):

Initial commit: Menambahkan model klasifikasi wajah dan aplikasi Gradio

Browse files
.gitattributes ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ *.keras filter=lfs diff=lfs merge=lfs -text
2
+ *.safetensors filter=lfs diff=lfs merge=lfs -text
3
+ *.bin filter=lfs diff=lfs merge=lfs -text
app.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import numpy as np
3
+ from PIL import Image
4
+ import tensorflow as tf
5
+ from typing import List, Dict
6
+
7
+ # Pastikan urutan ini sama persis dengan urutan saat training Anda
8
+ LABELS: List[str] = ["Heart", "Oblong", "Oval", "Round", "Square"]
9
+ IMG_SIZE = 244
10
+
11
+ # Fungsi ini harus meniru persis apa yang dilakukan `preprocess_input` dari EfficientNet
12
+ def preprocess_image(image: Image.Image) -> np.ndarray:
13
+ """
14
+ Mengubah ukuran gambar dan melakukan preprocessing yang sesuai untuk EfficientNet.
15
+ """
16
+ # Pastikan gambar dalam format RGB
17
+ if image.mode != "RGB":
18
+ image = image.convert("RGB")
19
+
20
+ # Ubah ukuran gambar
21
+ image = image.resize((IMG_SIZE, IMG_SIZE))
22
+
23
+ # Konversi ke array numpy
24
+ image_array = np.asarray(image)
25
+
26
+ # Tambahkan dimensi batch
27
+ image_array = np.expand_dims(image_array, axis=0)
28
+
29
+ # Gunakan fungsi preprocessing bawaan dari EfficientNet
30
+ # Ini akan menormalisasi piksel ke rentang [-1, 1]
31
+ processed_array = tf.keras.applications.efficientnet.preprocess_input(image_array)
32
+
33
+ return processed_array
34
+
35
+
36
+ # --- 3. Muat Model Anda ---
37
+ class FaceShapeModel:
38
+ def __init__(self, model_path: str = "best_model_antioverfit.keras") -> None:
39
+ """Memuat model Keras saat kelas diinisialisasi."""
40
+ try:
41
+ # Kita tidak perlu meng-compile model untuk inferensi
42
+ self.model = tf.keras.models.load_model(model_path, compile=False)
43
+ print("Model berhasil dimuat.")
44
+ except Exception as e:
45
+ print(f"Error saat memuat model: {e}")
46
+ self.model = None
47
+
48
+ def predict_image(self, image: Image.Image) -> Dict[str, float]:
49
+ """Melakukan prediksi pada satu gambar."""
50
+ if not self.model:
51
+ return {"Error": "Model tidak dapat dimuat."}
52
+
53
+ processed_input = preprocess_image(image)
54
+
55
+ preds = self.model.predict(processed_input)[0]
56
+
57
+ # Buat dictionary hasil {label: skor}
58
+ confidences = {label: float(score) for label, score in zip(LABELS, preds)}
59
+
60
+ return confidences
61
+
62
+ # Buat instance dari model kita
63
+ model = FaceShapeModel()
64
+
65
+ def predict(image_pil: Image.Image) -> Dict[str, float]:
66
+ """Fungsi wrapper yang akan dipanggil oleh Gradio."""
67
+ return model.predict_image(image_pil)
68
+
69
+
70
+ # --- 4. Buat Antarmuka Gradio ---
71
+ with gr.Blocks(theme=gr.themes.Soft()) as iface:
72
+ gr.Markdown(
73
+ """
74
+ # 🤖 Deteksi Bentuk Wajah (Indonesia)
75
+ Unggah foto wajah Anda untuk mengetahui bentuknya. Model ini dilatih menggunakan arsitektur EfficientNetB2.
76
+ Untuk hasil terbaik, gunakan foto di mana wajah terlihat jelas menghadap ke depan.
77
+ """
78
+ )
79
+ with gr.Row():
80
+ with gr.Column(scale=1):
81
+ image_input = gr.Image(type="pil", label="Unggah Gambar Wajah")
82
+ submit_btn = gr.Button("Prediksi Bentuk Wajah", variant="primary")
83
+ with gr.Column(scale=1):
84
+ label_output = gr.Label(num_top_classes=3, label="Hasil Prediksi")
85
+
86
+ gr.Examples(
87
+ examples=[
88
+ ],
89
+ inputs=image_input,
90
+ outputs=label_output,
91
+ fn=predict,
92
+ cache_examples=True
93
+ )
94
+
95
+ submit_btn.click(fn=predict, inputs=image_input, outputs=label_output)
96
+
97
+ if __name__ == "__main__":
98
+ iface.launch()
99
+
config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": ["EfficientNetB2"],
3
+ "image_size": 244,
4
+ "id2label": {
5
+ "0": "Heart",
6
+ "1": "Oblong",
7
+ "2": "Oval",
8
+ "3": "Round",
9
+ "4": "Square"
10
+ },
11
+ "label2id": {
12
+ "Heart": 0,
13
+ "Oblong": 1,
14
+ "Oval": 2,
15
+ "Round": 3,
16
+ "Square": 4
17
+ }
18
+ }
inference.py ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import numpy as np
2
+ from PIL import Image
3
+ import tensorflow as tf
4
+ from typing import List, Dict
5
+
6
+ LABELS: List[str] = ["Heart", "Oblong", "Oval", "Round", "Square"]
7
+ IMG_SIZE = 244
8
+
9
+ # Logika untuk mempersiapkan gambar sebelum prediksi
10
+ def preprocess_image(image: Image.Image) -> np.ndarray:
11
+ """
12
+ Mengubah ukuran gambar dan melakukan preprocessing yang sesuai untuk EfficientNet.
13
+ """
14
+ if image.mode != "RGB":
15
+ image = image.convert("RGB")
16
+
17
+ image = image.resize((IMG_SIZE, IMG_SIZE))
18
+
19
+ image_array = np.asarray(image)
20
+ image_array = np.expand_dims(image_array, axis=0)
21
+
22
+ processed_array = tf.keras.applications.efficientnet.preprocess_input(image_array)
23
+
24
+ return processed_array
25
+
26
+ # Semua logika terkait TensorFlow (memuat dan menjalankan model) ada di sini
27
+ class FaceShapeModel:
28
+
29
+ def __init__(self, model_path: str = "models/best_model_antioverfit.keras") -> None:
30
+ """Memuat model Keras saat kelas diinisialisasi."""
31
+ try:
32
+ self.model = tf.keras.models.load_model(model_path, compile=False)
33
+ print("Model berhasil dimuat dari inference.py.")
34
+ except Exception as e:
35
+ print(f"Error saat memuat model di inference.py: {e}")
36
+ self.model = None
37
+
38
+ def predict_image(self, image: Image.Image) -> Dict[str, float]:
39
+ """Melakukan prediksi pada satu gambar."""
40
+ if not self.model:
41
+ return {"Error": "Model tidak dapat dimuat."}
42
+
43
+ processed_input = preprocess_image(image)
44
+
45
+ preds = self.model.predict(processed_input)[0]
46
+
47
+ confidences = {label: float(score) for label, score in zip(LABELS, preds)}
48
+
49
+ return confidences
50
+
51
+ # Inisialisasi model sekali saja
52
+ model_instance = FaceShapeModel()
53
+
54
+ def predict(image_pil: Image.Image) -> Dict[str, float]:
55
+ """Fungsi wrapper yang akan dipanggil oleh Gradio dari app.py."""
56
+ if model_instance:
57
+ return model_instance.predict_image(image_pil)
58
+ return {"Error": "Instance model tidak tersedia."}
59
+
models/best_model_antioverfit.keras ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:9b24b0be88c9acdf9b741bcd62f1140176708f47e99c05d0825e9945090143c5
3
+ size 32294637
requirements.txt ADDED
File without changes