Alstears commited on
Commit
a4bfda2
·
verified ·
1 Parent(s): 82b5db4

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +23 -20
app.py CHANGED
@@ -26,7 +26,7 @@ ALLOWED_EXT = {"png", "jpg", "jpeg", "webp"}
26
  ROOT_DIR = "."
27
  MODEL_FILES = ["ckpt_best_v4_epoch8.pth", "ckpt_best_v4_epoch14.pth"]
28
 
29
- # Threshold murni hasil optimasi batas overlap data pengujian Anda
30
  MODEL_THRESHOLD = 0.615
31
 
32
  # ==========================================
@@ -95,14 +95,15 @@ def startup_event():
95
  raise RuntimeError(f"Startup digagalkan server: {e}")
96
 
97
  # ==========================================
98
- # 🔬 LAB FORENSIK DIGITAL - PURE EMSEMBLE ENGINE
99
  # ==========================================
100
  def run_full_forensic_pipeline(img_pil: Image.Image, img_cv, file_bytes, filename):
101
  img_gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
102
  h, w, c = img_cv.shape
103
 
104
- # Penghitung indikator palsu biner (Hanya dipertahankan untuk info sekunder JSON)
105
  poin_penalti_fake = 0
 
106
 
107
  # Deteksi Otomatis Jalur Kompresi WhatsApp via Nama Berkas
108
  fname_lower = filename.lower()
@@ -117,6 +118,7 @@ def run_full_forensic_pipeline(img_pil: Image.Image, img_cv, file_bytes, filenam
117
  exif = img_pil._getexif()
118
  step1 = "Ada metadata EXIF (Kamera Asli)" if exif else "Metadata kosong (Khas Gambar AI/Screenshot)"
119
  if not exif and not is_whatsapp:
 
120
  poin_penalti_fake += 1
121
 
122
  # [Step 2/12] Analisis Pixel (Komite Binary + TTA)
@@ -131,17 +133,19 @@ def run_full_forensic_pipeline(img_pil: Image.Image, img_cv, file_bytes, filenam
131
  preds14 = F.softmax(models_ensemble[1](batch_t), dim=1).cpu().numpy()
132
  probs_epoch14 = np.mean(preds14, axis=0)
133
 
134
- # Perhitungan bobot kombinasi biner untuk kelas FAKE (indeks 1)
135
  prob_fake_raw = float((0.4 * probs_epoch8[1]) + (0.6 * probs_epoch14[1]))
136
  step2 = f"Score Indikasi AI: {prob_fake_raw * 100:.1f}%"
137
 
138
- if prob_fake_raw >= MODEL_THRESHOLD:
 
 
139
  poin_penalti_fake += 1
140
 
141
  # [Step 3/12] Analisis Pola Sensor CFA
142
  diff_cfa = np.mean(np.abs(img_gray[1:, :] - img_gray[:-1, :]))
143
  step3 = "Pola interpolasi mulus alami" if diff_cfa < 15.0 else "Anomali interpolasi piksel buatan terdeteksi"
144
  if diff_cfa >= 15.0 and not is_whatsapp:
 
145
  poin_penalti_fake += 1
146
 
147
  # [Step 4/12] Pencarian jejak Hex/Binary
@@ -197,15 +201,14 @@ def run_full_forensic_pipeline(img_pil: Image.Image, img_cv, file_bytes, filenam
197
  poin_penalti_fake += 1
198
 
199
  # =======================================================
200
- # ⚖️ KEPUTUSAN MURNI MATEMATIKA MODEL ENSEMBLE (SAY NO TO 60%)
201
  # =======================================================
202
- # Mengembalikan kendali penuh tingkat keakuratan ke persenan halus model
203
- if prob_fake_raw >= MODEL_THRESHOLD:
204
- prediction = "AI"
205
- confidence = prob_fake_raw * 100
206
  else:
207
  prediction = "REAL"
208
- confidence = (1.0 - prob_fake_raw) * 100
209
 
210
  forensic_logs = {
211
  "step_1": f"[Step 1/12] Metadata: {step1}",
@@ -231,9 +234,9 @@ def run_full_forensic_pipeline(img_pil: Image.Image, img_cv, file_bytes, filenam
231
  def root():
232
  return {
233
  "status": "online",
234
- "engine": "Pure Ensemble Deep Learning Engine (Fine Confidence)",
235
  "models_loaded": len(models_ensemble) == 2,
236
- "model_threshold": f"{MODEL_THRESHOLD * 100}%"
237
  }
238
 
239
  @app.post("/predict")
@@ -257,22 +260,22 @@ async def predict(file: UploadFile = File(...)):
257
  if img_cv is None:
258
  raise ValueError("File korup atau struktur piksel tidak valid")
259
 
260
- # Eksekusi pipeline murni
261
  prediction, confidence, raw_score, forensic_steps, is_monochrome, active_penalties = run_full_forensic_pipeline(
262
  img_pil, img_cv, file_bytes, filename
263
  )
264
 
265
  return {
266
  "filename": filename,
267
- "prediction": prediction, # "REAL" atau "AI" murni komite binary
268
- "confidence": f"{confidence}%", # Nilai persenan halus (misal: 95.5%, 81.3%)
269
- "raw_deep_learning_score": f"{raw_score}%", # Skor murni kelas FAKE
270
  "active_fake_indicators": f"{active_penalties} dari 5",
271
- "is_monochrome_detected": is_monochrome, # Trigger Warning Banner jika gambar hitam-putih
272
- "forensic_analysis_logs": forensic_steps # Log 12 langkah lengkap untuk drop-down UI
273
  }
274
  except Exception as e:
275
- raise HTTPException(status_code=500, detail=f"Gagal memproses analisis forensik: {str(e)}")
276
 
277
  @app.post("/save-feedback")
278
  async def save_feedback(file: UploadFile = File(...), correct_label: str = Form(...)):
 
26
  ROOT_DIR = "."
27
  MODEL_FILES = ["ckpt_best_v4_epoch8.pth", "ckpt_best_v4_epoch14.pth"]
28
 
29
+ # Threshold murni untuk filter internal model Deep Learning
30
  MODEL_THRESHOLD = 0.615
31
 
32
  # ==========================================
 
95
  raise RuntimeError(f"Startup digagalkan server: {e}")
96
 
97
  # ==========================================
98
+ # 🔬 LAB FORENSIK DIGITAL - WITH WHATSAPP BYPASS
99
  # ==========================================
100
  def run_full_forensic_pipeline(img_pil: Image.Image, img_cv, file_bytes, filename):
101
  img_gray = cv2.cvtColor(img_cv, cv2.COLOR_BGR2GRAY)
102
  h, w, c = img_cv.shape
103
 
104
+ # Inisialisasi Poin Penalti untuk Penggabungan Keputusan
105
  poin_penalti_fake = 0
106
+ total_aturan = 5
107
 
108
  # Deteksi Otomatis Jalur Kompresi WhatsApp via Nama Berkas
109
  fname_lower = filename.lower()
 
118
  exif = img_pil._getexif()
119
  step1 = "Ada metadata EXIF (Kamera Asli)" if exif else "Metadata kosong (Khas Gambar AI/Screenshot)"
120
  if not exif and not is_whatsapp:
121
+ # Penalti dinonaktifkan untuk WhatsApp karena kompresi sistem WA pasti menghapus EXIF
122
  poin_penalti_fake += 1
123
 
124
  # [Step 2/12] Analisis Pixel (Komite Binary + TTA)
 
133
  preds14 = F.softmax(models_ensemble[1](batch_t), dim=1).cpu().numpy()
134
  probs_epoch14 = np.mean(preds14, axis=0)
135
 
 
136
  prob_fake_raw = float((0.4 * probs_epoch8[1]) + (0.6 * probs_epoch14[1]))
137
  step2 = f"Score Indikasi AI: {prob_fake_raw * 100:.1f}%"
138
 
139
+ # Aturan Khusus WhatsApp: Naikkan batas threshold model AI agar tidak sensitif pada noise rusak WA
140
+ THRESHOLD_MODEL_ACTUAL = 0.85 if is_whatsapp else MODEL_THRESHOLD
141
+ if prob_fake_raw >= THRESHOLD_MODEL_ACTUAL:
142
  poin_penalti_fake += 1
143
 
144
  # [Step 3/12] Analisis Pola Sensor CFA
145
  diff_cfa = np.mean(np.abs(img_gray[1:, :] - img_gray[:-1, :]))
146
  step3 = "Pola interpolasi mulus alami" if diff_cfa < 15.0 else "Anomali interpolasi piksel buatan terdeteksi"
147
  if diff_cfa >= 15.0 and not is_whatsapp:
148
+ # Penalti dinonaktifkan untuk WhatsApp karena kompresi WA merusak interpolasi alami piksel sensor
149
  poin_penalti_fake += 1
150
 
151
  # [Step 4/12] Pencarian jejak Hex/Binary
 
201
  poin_penalti_fake += 1
202
 
203
  # =======================================================
204
+ # KETOK PALU KEPUTUSAN GABUNGAN MATEMATIKA MULTI-EVIDENCE
205
  # =======================================================
206
+ if poin_penalti_fake >= 3:
207
+ prediction = "AI" # Menyesuaikan label tampilan sistem frontend web Anda ("AI" / "REAL")
208
+ confidence = (poin_penalti_fake / total_aturan) * 100
 
209
  else:
210
  prediction = "REAL"
211
+ confidence = ((total_aturan - poin_penalti_fake) / total_aturan) * 100
212
 
213
  forensic_logs = {
214
  "step_1": f"[Step 1/12] Metadata: {step1}",
 
234
  def root():
235
  return {
236
  "status": "online",
237
+ "engine": "Hybrid Integrated Forensic Engine (WhatsApp Bypass Fixed)",
238
  "models_loaded": len(models_ensemble) == 2,
239
+ "hybrid_voting_rules_count": 5
240
  }
241
 
242
  @app.post("/predict")
 
260
  if img_cv is None:
261
  raise ValueError("File korup atau struktur piksel tidak valid")
262
 
263
+ # Eksekusi pipeline terintegrasi baru dengan parameter operan filename
264
  prediction, confidence, raw_score, forensic_steps, is_monochrome, active_penalties = run_full_forensic_pipeline(
265
  img_pil, img_cv, file_bytes, filename
266
  )
267
 
268
  return {
269
  "filename": filename,
270
+ "prediction": prediction,
271
+ "confidence": f"{confidence}%",
272
+ "raw_deep_learning_score": f"{raw_score}%",
273
  "active_fake_indicators": f"{active_penalties} dari 5",
274
+ "is_monochrome_detected": is_monochrome,
275
+ "forensic_analysis_logs": forensic_steps
276
  }
277
  except Exception as e:
278
+ raise HTTPException(status_code=500, detail=f"Gagal memproses analisis gabungan forensik: {str(e)}")
279
 
280
  @app.post("/save-feedback")
281
  async def save_feedback(file: UploadFile = File(...), correct_label: str = Form(...)):