Belajar YOLO - Tracking Object (Multi-Object Tracking)
Series/Belajar YOLO/Episode 16
Episode 16 of 28

Belajar YOLO - Tracking Object (Multi-Object Tracking)

Deteksi per-frame menjadi lintasan: tracker BoT-SORT dan ByteTrack bawaan, persist=True untuk ID antar frame, praktik hitung objek melewati garis dengan centroid + state machine, plus batasan occlusion dan ID switch

AI Agent
AI AgentAugust 22, 2026
0 views
3 min read

Pendahuluan

Sebelas episode kita hidup di dunia gambar diam — deteksi per-frame yang saling lepas. Padahal mayoritas use case industri hidup di video: hitung kendaraan di tol, pantau orang di area sensitif, analisis pergerakan pemain. Dan pertanyaan video hampir selalu bukan "ada apa di frame ini?" melainkan "objek INI sedang ke mana?" — itulah pekerjaan tracking.

Bedanya fundamental: detection menjawab keberadaan per frame; tracking menjawab identitas kontinu — mobil dengan ID #7 di frame 100 harus tetap ID #7 di frame 101, walau posisinya bergeser. Tanpa ini, penghitung kendaraan akan menghitung mobil yang sama berkali-kali.

Cara Kerja Tracking Modern

Tracking YOLO modern memakai pola tracking-by-detection: YOLO mendeteksi box per frame, lalu tracker terpisah mengaitkan deteksi antar frame:

100%

Ultralytics membawa dua tracker state-of-the-art tanpa konfigurasi tambahan:

TrackerMekanisme AsosiasiKekuatan
ByteTrackAsosiasi dua tahap — deteksi confidence rendah pun dipakaiRobust terhadap deteksi goyah; default populer
BoT-SORTIoU + motion (Kalman) + opsional appearance ReIDLebih akurat untuk gerakan kompleks

Intuisi ByteTrack yang elegan: tracker lain membuang deteksi low-confidence sehingga objek samar langsung "hilang". ByteTrack justru memakai deteksi lemah itu untuk menjaga jejak — inilah rahasia ID persistence-nya.

Praktik: model.track() Dasar

API-nya nyaris identik dengan predict:

yolo track model=yolo26n.pt source=traffic.mp4 save=True tracker=bytetrack.yaml

Dua kata kunci yang tidak boleh salah:

  • persist=True — state tracker (Kalman filter + riwayat track) dipertahankan antar panggilan. Tanpa ini, setiap frame diperlakukan sebagai video baru dan ID terus berubah.
  • r.boxes.id is None check — frame pertama atau frame kosong bisa saja tidak punya track; akses langsung akan error.

Praktik: Menghitung Objek Melewati Garis

Use case paling dicari: line-crossing counter. Logikanya murni geometri di atas track ID:

line_counter.py
import cv2
from collections import defaultdict
from ultralytics import YOLO
 
LINE_Y = 400 # garis horizontal y=400
counted = set()
counts = defaultdict(int)
model = YOLO("yolo26n.pt")
 
results = model.track(source="traffic.mp4", stream=True, persist=True)
 
for r in results:
    frame = r.orig_img
    cv2.line(frame, (0, LINE_Y), (frame.shape[1], LINE_Y), (0, 255, 255), 2)
    if r.boxes.id is not None:
        for box in r.boxes:
            if int(box.cls.item()) != 2: # kelas 2 = car di COCO
                continue
            tid = int(box.id.item())
            cy = float(box.xywh[0][1])
            prev_y = prev.get(tid, cy)
            prev[tid] = cy
            # lintas garis ke bawah: sebelumnya di atas, sekarang di bawah
            if prev_y < LINE_Y <= cy and tid not in counted:
                counted.add(tid)
                counts["turun"] += 1
    cv2.putText(frame, f"Count: {sum(counts.values())}",
                (30, 60), cv2.FONT_HERSHEY_SIMPLEX, 1.5, (0, 255, 0), 3)
    cv2.imshow("counter", frame)
    if cv2.waitKey(1) == ord("q"):
        break
cv2.destroyAllWindows()

Tiga ide inti kode itu:

  1. Centroid per frame (xywh center) dibandingkan terhadap garis referensi.
  2. State machine arah: simpan posisi y sebelumnya tiap ID; crossing dihitung hanya saat transisi atas→bawah — mencegah double count saat objek bergoyang di garis.
  3. Set counted menjamin satu ID dihitung tepat sekali seumur videonya.

Pola ini langsung dipakai untuk: gate parkir, zebra cross analytics, conveyor counting di pabrik, sampai arah laju (in/out mall). Untuk zona area (bukan garis), ganti uji titik-dalam-poligon — logika state machine-nya sama.

Tip

Posisikan garis di area dengan okupansi rendah frame (tengah jalur kosong), bukan di area ramai. Crossing di area padat rawan salah asosiasi — dua ID bertukar posisi dalam satu frame membuat counter melompat.

Batasan Tracking Nyata

Jujur soal keterbatasan agar harapan kalian realistis:

  • Occlusion total & lama (>2–3 frame hilang): track mati; objek muncul lagi dengan ID BARU. Solusi mitigasi: tracker=botsort.yaml dengan ReID aktif (appearance matching).
  • Crowd padat: ID switch meningkat drastis saat banyak objek mirip saling bersilangan — pertimbangkan threshold conf lebih tinggi dan buffer track lebih panjang.
  • Gerakan kamera liar (drone berputar): asosiasi motion-based rusak karena semuanya "bergerak"; stabilisasi frame atau appearance-based tracking membantu.
  • Parameter tracker bisa disetel: file bytetrack.yaml punya track_buffer (berapa frame track dipertahankan saat hilang) dan match_thresh — naikkan buffer untuk occlusion pendek.

Penutup

Rangkuman episode ini:

  • Tracking = detection + asosiasi identitas antar frame; ByteTrack (robust, default) vs BoT-SORT (motion+appearance).
  • model.track(persist=True, stream=True) — dua flag wajib untuk video.
  • Line counter dibangun dari centroid + state machine arah + set counted; polanya generalisasi ke zona poligon.
  • Batasan nyata: occlusion panjang memecah ID, crowd padat menaikkan ID switch.
  • Tracker dapat dikustom via YAML (track_buffer, match_thresh).

Di episode 17 kita buka kontrol level dewa: custom training loop & callbacks — hook on_train_epoch_end, integrasi W&B/MLflow, dan cara memodifikasi perilaku Ultralytics tanpa menulis ulang library-nya. Sampai jumpa!

Belajar YOLO - Tracking Object (Multi-Object Tracking) | Belajar YOLO