Fondasi data sebelum training: struktur folder images/labels, anatomi file txt normalized (class x y w h), data.yaml, perbandingan tools annotation Roboflow/CVAT/Label Studio, trik auto-labeling, dan praktik menyiapkan dataset custom kecil

Enam episode terakhir kita hidup dari model pretrained. Mulai episode ini kita beralih ke fase yang menentukan 80% keberhasilan project vision nyata: menyiapkan dataset sendiri.
Percayalah pada pola yang berulang di industri: model yang "gagal" hampir selalu bukan karena YOLO-nya buruk, melainkan karena datanya kacau — label tidak konsisten, format salah, atau split train/val bocor. Episode ini mengajarkan fondasinya: bagaimana tepatnya YOLO membaca dataset, tool apa untuk menganotasi, dan cara membangun dataset custom pertama kalian dengan benar sejak hari pertama.
Ultralytics mengharapkan layout yang konsisten:
datasets/
└── proyek-helm/
├── images/
│ ├── train/ # gambar training
│ │ ├── img_001.jpg
│ │ └── img_002.jpg
│ └── val/ # gambar validasi (JANGAN dari train!)
│ └── img_101.jpg
└── labels/
├── train/
│ ├── img_001.txt # satu txt per gambar
│ └── img_002.txt
└── val/
└── img_101.txtAturan pentingnya:
.txt dengan nama yang sama persis (img_001.jpg ↔ img_001.txt).train vs val harus disjoint — gambar yang sama tidak boleh ada di keduanya. Pelanggaran paling umum yang membuat metrik val bohong..txt kosong — justru berguna sebagai background images untuk menekan false positive.Isi setiap .txt adalah daftar baris, satu baris per objek:
1 0.481250 0.613194 0.234375 0.411111
0 0.152083 0.440972 0.104167 0.180556
1 0.790000 0.588194 0.150000 0.336111Format tiap baris — ingat kembali episode 1:
<class_id> <x_center> <y_center> <width> <height>Semua koordinat dan ukuran dinormalisasi 0–1 relatif ke lebar/tinggi gambar. Jadi box lebar 300 piksel di gambar 1280 piksel ditulis 0.234375.
Konversi manual sering dibutuhkan saat migrasi dari anotasi lama:
def voc_to_yolo(xmin, ymin, xmax, ymax, w_img, h_img):
xc = ((xmin + xmax) / 2) / w_img
yc = ((ymin + ymax) / 2) / h_img
bw = (xmax - xmin) / w_img
bh = (ymax - ymin) / h_img
return xc, yc, bw, bh
# contoh: box [120, 340, 420, 870] di gambar 1280x960
print(voc_to_yolo(120, 340, 420, 870, 1280, 960))
# (0.2109375, 0.6302083333333334, 0.234375, 0.5520833333333334)Warning
Tiga bug dataset paling sering: (1) nilai > 1 karena lupa normalisasi, (2) class_id mulai dari 1 padahal harus 0-indexed, (3) x_center ditukar width. Semua ini tidak selalu error saat training — kadang hanya menghasilkan model jelek diam-diam. Visualisasi ulang anotasi kalian (teknik episode 1) adalah alat debug termurah.
data.yaml: Kontrak DatasetFile kecil ini yang memberitahu Ultralytics tentang dataset kalian:
path: /home/user/datasets/proyek-helm # root dataset
train: images/train # relatif terhadap path
val: images/val
nc: 3 # jumlah class
names:
0: person
1: helm
2: no-helmKaidah pentingnya:
path absolut atau relatif terhadap folder datasets/ default Ultralytics.names bisa juga list ([person, helm]) — tapi dict eksplisit lebih aman dari salah urutan.nc harus sama dengan jumlah entri names. Mismatch = error langsung saat build model.labels/train berisi polygon; untuk pose ada format keypoint tersendiri — prinsip foldernya sama.Menganotasi adalah pekerjaan paling membosankan sekaligus paling menentukan. Pilihan utamanya:
| Tool | Model Biaya | Kekuatan | Cocok Untuk |
|---|---|---|---|
| Roboflow | Freemium SaaS | End-to-end: annotate + augment + export format YOLO siap pakai | Tim kecil yang ingin cepat jalan |
| CVAT | Open source (self-host/cloud) | Matang, mendukung video interpolation & banyak task | Dataset besar, tim dengan infra |
| Label Studio | Open source + cloud | Multi-modal (image/text/audio), integrasi pipeline fleksibel | Project multi-jenis data |
Prinsip memilih: untuk belajar dan dataset < 500 gambar, Roboflow free tier sudah lebih dari cukup dan menyimpan kalian dari setup server. CVAT layak saat butuh anotasi video frame-by-frame dengan tracking assist. Label Studio unggul kalau satu tim mengelola banyak jenis data.
Model pretrained bisa menjadi anotator awal:
yolo predict model=yolo26n.pt source=raw_images/ save_txt=True save_conf=FalseHasil save_txt=True sudah dalam format YOLO! Alurnya:
Untuk domain khusus, kombinasi populer: Grounding DINO/YOLO-World untuk proposal box → manusia verifikasi → fine-tune YOLO. Pipeline auto-labeling semacam ini dipakai tim produksi untuk memangkas biaya anotasi hingga puluhan persen.
Mari bangun dataset mini (10–50 gambar/kelas cukup untuk latihan):
[x] Kumpulkan 20-50 gambar per kelas (kamera HP, Google Images, footage sendiri)
[x] Beri nama file konsisten: img_001.jpg, dst
[x] Anotasi via Roboflow/CVAT → export "YOLOv11/12 format"
[x] Split otomatis 80% train / 20% val (fitur Roboflow)
[x] Download & ekstrak ke datasets/proyek-helm/
[x] Cek data.yaml sesuai path lokalLalu verifikasi dataset kalian bisa dibaca Ultralytics sebelum training:
from ultralytics.data.utils import check_det_dataset
data = check_det_dataset("proyek-helm/data.yaml")
print("Train:", len(data["train"]), "| Val:", len(data["val"]))
print("Classes:", data["names"])Tip
Aturan jumlah data kasar untuk production-grade: 200+ gambar per kelas sebagai minimum serius, 1.500+ untuk kelas dengan variasi tinggi (pencahayaan, sudut). Untuk latihan series ini 20–50 per kelas cukup — prosesnya identik, cuma metriknya belum production-ready.
Rangkuman episode ini:
images/{train,val} paralel dengan labels/{train,val}, satu .txt per gambar.class_id x_center y_center width height, semuanya normalized 0–1.data.yaml adalah kontrak dataset: path, nc, names — mismatch = gagal cepat (itu bagus!).Di episode 9 akhirnya kita menyalakan training loop: model.train() dari scratch — hyperparameters inti (epochs, imgsz, batch), optimizer auto, apa yang terjadi di balik layar selama training, plus kapan strategi from scratch benar-benar masuk akal. Sampai jumpa!