vincentcps commited on
Commit
d665701
·
verified ·
1 Parent(s): 8ded0d1

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +48 -84
app.py CHANGED
@@ -1,13 +1,11 @@
1
  import os
2
  import io
3
- import numpy as np
4
  from PIL import Image
5
  from flask import Flask, request, jsonify, send_file
6
  from flask_cors import CORS
7
  import re
8
  import torch
9
- from transformers import AutoModelForImageClassification, AutoImageProcessor
10
- from typing import Dict, Any
11
 
12
  # =================================================================
13
  # 1. SETUP FLASK SERVER & CORS
@@ -16,95 +14,46 @@ app = Flask(__name__)
16
  CORS(app)
17
 
18
  # =================================================================
19
- # 2. SETUP MODEL AI & PREPROCESSING
20
  # =================================================================
21
  MODEL_NAME = "prithivMLmods/BrainTumor-Classification-Mini"
22
- model = None
23
- processor = None
24
- device = "cpu" # Default ke CPU untuk stabilitas Hugging Face Spaces
25
 
26
  def load_model():
27
- """Memuat model dan image processor secara eksplisit untuk menjamin preprocessing yang benar."""
28
- global model, processor, device
29
  try:
30
- print("⏳ Sedang memuat Model dan Processor AI ({})...".format(MODEL_NAME))
31
  device = "cuda" if torch.cuda.is_available() else "cpu"
32
-
33
- # Memuat Processor (WAJIB untuk Preprocessing yang Benar)
34
- processor = AutoImageProcessor.from_pretrained(MODEL_NAME)
35
-
36
- # Memuat Model
37
- model = AutoModelForImageClassification.from_pretrained(MODEL_NAME)
38
- model.to(device)
39
- model.eval() # Atur model ke mode evaluasi
40
-
41
- print(f"✅ Model dan Processor berhasil dimuat ke device: {device}")
42
  except Exception as e:
43
- print("❌ Gagal memuat model atau processor: {}".format(e))
44
- model = None
45
- processor = None
46
 
47
- # Panggil fungsi saat aplikasi dimuat oleh Gunicorn
48
  load_model()
49
 
50
- # Pemetaan label (diambil dari model's config, jika ada)
51
- LABEL_MAPPING_RAW = {
52
  'glioma': {'status': 'Tumor Terdeteksi', 'jenis': 'Glioma'},
53
  'meningioma': {'status': 'Tumor Terdeteksi', 'jenis': 'Meningioma'},
54
  'notumor': {'status': 'Tidak Ada Tumor', 'jenis': 'Tidak Ada'},
55
  'pituitary': {'status': 'Tumor Terdeteksi', 'jenis': 'Pituitary Tumor'}
56
  }
57
 
58
- # =================================================================
59
- # 3. FUNGSI PREDIKSI MANUAL (untuk Akurasi Tertinggi)
60
- # =================================================================
61
-
62
- def predict_manual(image: Image.Image) -> Dict[str, Any]:
63
- """Mengambil gambar PIL, mengolahnya dengan processor, dan memprediksi secara manual."""
64
- if model is None or processor is None:
65
- raise Exception("Model atau Processor belum siap.")
66
-
67
- # 1. Preprocessing Gambar menggunakan processor model
68
- inputs = processor(image, return_tensors="pt")
69
-
70
- # 2. Memindahkan input ke device yang benar (CPU/GPU)
71
- inputs = {k: v.to(device) for k, v in inputs.items()}
72
-
73
- # 3. Inference (prediksi)
74
- with torch.no_grad():
75
- outputs = model(**inputs)
76
- logits = outputs.logits
77
-
78
- # 4. Ambil Probabilitas dan Index Tertinggi
79
- probabilities = torch.nn.functional.softmax(logits, dim=-1)
80
- top_prob, top_index = torch.topk(probabilities, 1)
81
-
82
- # 5. Dapatkan Label
83
- # Mengambil label dari ID ke string (jika ada di model config)
84
- predicted_id = top_index.item()
85
- if model.config.id2label:
86
- raw_label = model.config.id2label[predicted_id]
87
- else:
88
- # Fallback jika id2label tidak ada (seperti pada prithivMLmods)
89
- # Kita harus berasumsi urutan index adalah: 0=glioma, 1=meningioma, 2=notumor, 3=pituitary
90
- index_to_label = ['glioma', 'meningioma', 'notumor', 'pituitary']
91
- raw_label = index_to_label[predicted_id] if predicted_id < len(index_to_label) else 'unknown'
92
-
93
- # 6. Formatting Output
94
- clean_key = raw_label.lower().replace(' ', '')
95
- result_data = LABEL_MAPPING_RAW.get(clean_key, {
96
- 'status': 'Hasil Tidak Dikenal',
97
- 'jenis': 'N/A'
98
- })
99
-
100
- return {
101
- "prediction_status": result_data['status'],
102
- "tumor_type": result_data['jenis'],
103
- "confidence": round(top_prob.item() * 100, 2)
104
- }
105
 
106
  # =================================================================
107
- # 4. ENDPOINT WEB SERVER (Host HTML)
108
  # =================================================================
109
 
110
  @app.route('/', methods=['GET'])
@@ -116,32 +65,47 @@ def serve_html():
116
  return f"<h1>Error: File index.html tidak ditemukan di server.</h1><p>Pastikan file index.html sudah di-COPY ke Docker container.</p><p>{e}</p>", 500
117
 
118
  # =================================================================
119
- # 5. ENDPOINT API (Predict)
120
  # =================================================================
121
 
122
  @app.route('/predict', methods=['POST'])
123
  def predict():
124
- """Endpoint utama untuk prediksi, menggunakan fungsi predict_manual yang akurat."""
125
-
 
 
126
  if 'file' not in request.files:
127
  return jsonify({"error": "no file uploaded"}), 400
128
 
129
  file = request.files['file']
130
 
131
  try:
132
- # 1. Baca file gambar dan konversi ke PIL Image
133
  image_bytes = file.read()
134
  image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
135
 
136
  except Exception as e:
137
- print(f"Error saat memproses gambar: {e}")
138
  return jsonify({"error": f"Gagal memproses gambar: {e}"}), 400
139
 
140
- # Lakukan Prediksi Manual
141
  try:
142
- result = predict_manual(image)
143
- return jsonify(result)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
144
 
145
  except Exception as e:
146
- print(f"Error saat prediksi: {e}")
147
- return jsonify({"error": f"Terjadi kesalahan saat menjalankan prediksi model: {e}"}), 500
 
1
  import os
2
  import io
 
3
  from PIL import Image
4
  from flask import Flask, request, jsonify, send_file
5
  from flask_cors import CORS
6
  import re
7
  import torch
8
+ from transformers import pipeline
 
9
 
10
  # =================================================================
11
  # 1. SETUP FLASK SERVER & CORS
 
14
  CORS(app)
15
 
16
  # =================================================================
17
+ # 2. SETUP MODEL AI (Kembali ke Pipeline Sederhana)
18
  # =================================================================
19
  MODEL_NAME = "prithivMLmods/BrainTumor-Classification-Mini"
20
+ classifier = None
 
 
21
 
22
  def load_model():
23
+ """Memuat model AI menggunakan pipeline standar."""
24
+ global classifier
25
  try:
26
+ print("⏳ Sedang memuat model AI ({})...".format(MODEL_NAME))
27
  device = "cuda" if torch.cuda.is_available() else "cpu"
28
+ classifier = pipeline(
29
+ "image-classification",
30
+ model=MODEL_NAME,
31
+ device=device
32
+ )
33
+ print("✅ Model {} berhasil dimuat ke device: {}".format(MODEL_NAME, device))
 
 
 
 
34
  except Exception as e:
35
+ print("❌ Gagal memuat model: {}".format(e))
36
+ classifier = None
 
37
 
 
38
  load_model()
39
 
40
+ # Pemetaan label
41
+ LABEL_MAPPING = {
42
  'glioma': {'status': 'Tumor Terdeteksi', 'jenis': 'Glioma'},
43
  'meningioma': {'status': 'Tumor Terdeteksi', 'jenis': 'Meningioma'},
44
  'notumor': {'status': 'Tidak Ada Tumor', 'jenis': 'Tidak Ada'},
45
  'pituitary': {'status': 'Tumor Terdeteksi', 'jenis': 'Pituitary Tumor'}
46
  }
47
 
48
+ def clean_label(raw_label):
49
+ """Membersihkan label mentah dari model."""
50
+ match = re.search(r'(glioma|meningioma|notumor|pituitary)', raw_label, re.IGNORECASE)
51
+ if match:
52
+ return match.group(0).lower()
53
+ return raw_label.lower()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
54
 
55
  # =================================================================
56
+ # 3. ENDPOINT WEB SERVER (Host HTML)
57
  # =================================================================
58
 
59
  @app.route('/', methods=['GET'])
 
65
  return f"<h1>Error: File index.html tidak ditemukan di server.</h1><p>Pastikan file index.html sudah di-COPY ke Docker container.</p><p>{e}</p>", 500
66
 
67
  # =================================================================
68
+ # 4. ENDPOINT API (Predict)
69
  # =================================================================
70
 
71
  @app.route('/predict', methods=['POST'])
72
  def predict():
73
+ """Endpoint utama untuk prediksi."""
74
+ if classifier is None:
75
+ return jsonify({"error": "Model AI belum dimuat atau gagal dimuat."}), 500
76
+
77
  if 'file' not in request.files:
78
  return jsonify({"error": "no file uploaded"}), 400
79
 
80
  file = request.files['file']
81
 
82
  try:
 
83
  image_bytes = file.read()
84
  image = Image.open(io.BytesIO(image_bytes)).convert("RGB")
85
 
86
  except Exception as e:
 
87
  return jsonify({"error": f"Gagal memproses gambar: {e}"}), 400
88
 
89
+ # Lakukan Prediksi
90
  try:
91
+ # Gunakan pipeline
92
+ results = classifier(images=image, top_k=1)
93
+
94
+ result = results[0]
95
+ raw_label = result['label']
96
+ confidence = result['score'] * 100
97
+
98
+ clean_key = clean_label(raw_label)
99
+ result_data = LABEL_MAPPING.get(clean_key, {
100
+ 'status': 'Hasil Tidak Dikenal',
101
+ 'jenis': 'N/A'
102
+ })
103
+
104
+ return jsonify({
105
+ "prediction_status": result_data['status'],
106
+ "tumor_type": result_data['jenis'],
107
+ "confidence": round(confidence, 2)
108
+ })
109
 
110
  except Exception as e:
111
+ return jsonify({"error": "Terjadi kesalahan saat menjalankan prediksi model."}), 500