Mengalahkan musuh terkeras detection: objek kecil di bawah 32 piksel, crowd padat, occlusion, low-light, dan aerial imagery — dengan resolusi tinggi, tiling SAHI, copy-paste augmentation, dan P2 head

Semua teknik training dan optimasi yang kita pelajari bekerja baik — sampai objeknya kecil. Deteksi objek di bawah 32×32 piksel adalah masalah yang membuat mAP project nyata anjlok puluhan poin, dan tidak ada hyperparameter yang menyelamatkannya.
Episode ini membedah kenapa objek kecil secara fundamental menyiksa CNN (jawabannya ada di episode 3), lalu membongkar arsenal solusinya berurutan dari termurah sampai termahal: resolusi tinggi, slicing inference dengan SAHI, augmentasi khusus, hingga modifikasi arsitektur P2 head. Ditambah protokol untuk hard case lain: crowd, occlusion, dan low-light.
Kembali ke mekanika backbone (episode 3): gambar input didownsampling bertahap — pada imgsz=640, feature map terakhir hanya ~20×20. Sebuah mobil 24 piksel di input menjadi kurang dari satu sel feature map pada level P5. Informasinya bukan "kecil" — ia praktis menguap sebelum head sempat melihatnya.
Input 640x640 → objek 24px = 0.14% area gambar
P3 (80x80) → sisa ~3 px : masih terlihat
P4 (40x40) → sisa <1 px : samar
P5 (20x20) → sisa 0.25 px : HILANGKonsekuensinya: semua solusi objek kecil bermuara ke dua strategi — beri lebih banyak piksel atau jaga objek tetap besar di feature map.
imgsz)Termurah dan pertama dicoba:
yolo detect train model=yolo26s.pt data=data.yaml imgsz=1280 batch=-1Aturan mainnya (diperluas dari episode 12):
Resolusi tinggi menang jika objek kecil tersebar merata. Tapi untuk citra aerial 4000×3000 piksel dengan objek 15 piksel — bahkan 1280 tidak cukup, karena downsampling global tetap menenggelamkannya. Di sinilah solusi #2 masuk.
Ide brilian yang sederhana: jangan biarkan model melihat gambar raksasa yang di-resize — potong gambar menjadi tile, inferensi tiap tile pada resolusi penuh, lalu gabungkan hasilnya:
Library SAHI membuatnya beberapa baris:
from sahi import AutoDetectionModel
from sahi.predict import get_sliced_prediction
model = AutoDetectionModel.from_pretrained(
model_type="ultralytics",
model_path="best.pt",
confidence_threshold=0.25,
)
result = get_sliced_prediction(
"drone_shot.jpg",
model,
slice_height=640, slice_width=640,
overlap_height_ratio=0.2, overlap_width_ratio=0.2,
)
for obj in result.object_prediction_list:
print(obj.category.name, round(obj.score.value, 2),
[round(v) for v in list(obj.bbox.to_xyxy())])Parameter kunci: overlap 0.2 — tile bertumpuk sedikit agar objek yang kepotong tepi tile tetap tertangkap utuh di tile tetangga. Trade-off jujurnya: waktu inference naik proporsional jumlah tile (gambar 4K ≈ 35–50 tile). Karena itu pola produksinya lazim dua tahap: preview cepat full-image → SAHI hanya di region of interest.
Note
SAHI juga punya versi training: sliced fine-tuning — dataset aerial dipotong jadi tile sebelum dilatih, sehingga model belajar dari objek yang relatif "besar" di tiap tile. Untuk proyek drone serius, kombinasi sliced-training + SAHI-inference adalah standar de facto.
Objek kecil jarang = contoh langka. Copy-paste augmentation memotong instance dari gambar asli lalu menempelkannya ke gambar lain — memperbanyak contoh tanpa anotasi baru:
from ultralytics import YOLO
YOLO("yolo26n.pt").train(
data="aerial/data.yaml",
imgsz=1280,
copy_paste=0.3, # 30% peluang instance ditempel ulang
)Syarat mutlaknya mask segmentation (instance dipotong mengikuti bentuk). Jaga kesadaran realisme: tempelkan mobil ke atap gedung dan dataset kalian belajar hal yang salah.
Jika semua di atas masih kurang: tambahkan head prediksi pada P2 — feature map paling halus (stride 4) yang secara default dilewati head YOLO. Objek 8–16 piksel yang hilang di P3 masih hidup di P2.
Caranya: salin config model, tambahkan layer P2 di bagian head: YAML, dan daftarkan output-nya ke daftar Detect (menjadi Detect(P2, P3, P4, P5)). Konsekuensinya jujur: feature map P2 besar → komputasi & VRAM naik signifikan, latency ikut naik. Gunakan hanya ketika target benar-benar ekstrem kecilnya (deteksi burung, kabel rusut, cacat mikro).
| Kasus | Akar Masalah | Senjata Utama |
|---|---|---|
| Crowd padat | Ribuan instance mirip, NMS saling hapus | Resolusi naik + conf threshold disetel; pertimbangkan model crowd-spesifik |
| Occlusion berat | Objek tersembunyi parsial | Anotasi bagian terlihat konsisten; augmentasi occlusion sintetis |
| Low-light | SNR rendah, warna hilang | Pra-enhancement (CLAHE/denoise) atau fine-tune data malam; hindari HSV agresif |
| Aerial top-down | Perspektif tak lazim + objek kecil | Fine-tune domain + rotasi augmentasi + OBB (episode 6) |
Pola umumnya: hard case adalah masalah distribusi data, bukan bug model. Solusi permanennya hampir selalu mengumpulkan/menyimulasikan data kondisi tersebut — trik arsitektur hanya menjembatani.
1. Visualisasi label di atas gambar (episode 1) — pastikan anotasinya ada!
2. Ukur baseline mAP_small vs mAP_all — quantifikasi masalah
3. imgsz 640→1280, ukur lagi
4. Masih gagal? SAHI inference (+ sliced training utk aerial)
5. Contoh langka? copy_paste augmentation
6. Ekstrem? P2 head — sadari biaya latensinya
7. Satu perubahan per eksperimen (disiplin episode 15!)Rangkuman episode ini:
Di episode 24 kita zoom out dan bertanya pertanyaan tabu: apakah YOLO selalu jawaban terbaik? Perbandingan YOLO vs RF-DETR, DETR, dan RTMDet — lisensi, akurasi, throughput, dan cara memilih dengan kepala dingin. Sampai jumpa!