Spaces:
Sleeping
Sleeping
| """ | |
| Batch-test backend menggunakan satu folder dengan naming convention: | |
| r1, r2, r3, ... β real | |
| f1, f2, f3, ... β fake | |
| Usage: | |
| 1. Pastiin app.py jalan di terminal lain | |
| 2. python test_batch.py "C:/Users/yourname/Downloads" | |
| atau | |
| python test_batch.py ~/Downloads | |
| """ | |
| import os, sys, glob, re, requests | |
| from collections import Counter | |
| if len(sys.argv) < 2: | |
| print("Usage: python test_batch.py /path/to/folder") | |
| print('Windows example: python test_batch.py "C:\\Users\\YourName\\Downloads"') | |
| print("Mac example: python test_batch.py ~/Downloads") | |
| sys.exit(1) | |
| folder = os.path.expanduser(sys.argv[1]) | |
| URL = "http://localhost:5000/analyze" | |
| if not os.path.isdir(folder): | |
| print(f"β Folder tidak ditemukan: {folder}") | |
| sys.exit(1) | |
| # Cari semua gambar | |
| EXTS = ["jpg", "jpeg", "png", "webp"] | |
| all_files = [] | |
| for ext in EXTS: | |
| all_files.extend(glob.glob(os.path.join(folder, f"*.{ext}"))) | |
| all_files.extend(glob.glob(os.path.join(folder, f"*.{ext.upper()}"))) | |
| # Klasifikasi berdasarkan prefix nama file (r1.jpg β real, f1.jpg β fake) | |
| pattern = re.compile(r"^([rf])(\d+)\.", re.IGNORECASE) | |
| labeled_files = [] | |
| for fp in all_files: | |
| name = os.path.basename(fp) | |
| m = pattern.match(name) | |
| if m: | |
| prefix = m.group(1).lower() | |
| true_label = "real" if prefix == "r" else "fake" | |
| idx = int(m.group(2)) | |
| labeled_files.append((fp, true_label, idx)) | |
| if not labeled_files: | |
| print(f"β Gak ada file dengan format r1.jpg / f1.jpg dst di {folder}") | |
| print(" File yang ada di folder:") | |
| for fp in sorted(all_files)[:10]: | |
| print(f" {os.path.basename(fp)}") | |
| sys.exit(1) | |
| # Sort: real dulu (sesuai index), terus fake | |
| labeled_files.sort(key=lambda x: (x[1], x[2])) | |
| print(f"β Ditemukan {len(labeled_files)} gambar berlabel di {folder}\n") | |
| stats = Counter() | |
| mistakes = [] | |
| current_label = None | |
| for fp, true_label, idx in labeled_files: | |
| # Print header tiap ganti kategori | |
| if true_label != current_label: | |
| count = sum(1 for _, t, _ in labeled_files if t == true_label) | |
| print(f"\n=== {true_label.upper()} ({count} files) ===") | |
| print(f"{'file':<25} {'pred':<6} {'p_fake':>9} {'ok'}") | |
| print("-" * 55) | |
| current_label = true_label | |
| try: | |
| with open(fp, "rb") as f: | |
| r = requests.post(URL, files={"image": f}, timeout=30) | |
| except requests.exceptions.ConnectionError: | |
| print(f"\nβ Backend gak nyala di {URL}") | |
| print(" Jalanin dulu: python app.py") | |
| sys.exit(1) | |
| if r.status_code != 200: | |
| print(f" ERROR on {fp}: {r.text}") | |
| continue | |
| d = r.json() | |
| pred = "fake" if d["is_fake"] else "real" | |
| ok = pred == true_label | |
| stats[(true_label, pred)] += 1 | |
| if not ok: | |
| mistakes.append((fp, true_label, pred, d["p_fake"])) | |
| mark = "OK" if ok else "WRONG" | |
| name = os.path.basename(fp)[:23] | |
| print(f"{name:<25} {pred:<6} {d['p_fake']:>8.2f}% {mark}") | |
| # Summary | |
| print("\n" + "=" * 55) | |
| print("CONFUSION MATRIX") | |
| print("=" * 55) | |
| print(f"{'':<10} {'pred_real':>12} {'pred_fake':>12}") | |
| print(f"{'true_real':<10} {stats[('real','real')]:>12} {stats[('real','fake')]:>12}") | |
| print(f"{'true_fake':<10} {stats[('fake','real')]:>12} {stats[('fake','fake')]:>12}") | |
| total = sum(stats.values()) | |
| correct = stats[("real","real")] + stats[("fake","fake")] | |
| if total: | |
| print(f"\nAccuracy: {correct}/{total} = {100*correct/total:.1f}%") | |
| n_real = stats[("real","real")] + stats[("real","fake")] | |
| n_fake = stats[("fake","real")] + stats[("fake","fake")] | |
| if n_real: | |
| print(f"Real recall: {stats[('real','real')]}/{n_real} = {100*stats[('real','real')]/n_real:.1f}%") | |
| if n_fake: | |
| print(f"Fake recall: {stats[('fake','fake')]}/{n_fake} = {100*stats[('fake','fake')]/n_fake:.1f}%") | |
| if mistakes: | |
| print(f"\n{len(mistakes)} MISCLASSIFIED:") | |
| for fp, t, p, pf in mistakes: | |
| print(f" {os.path.basename(fp):<25} true={t:<5} pred={p:<5} p_fake={pf:.2f}%") |