Pengolahan Citra · Materi 11

YOLO Object Detection pada Gambar

Menyusun program penghitung objek dengan filter kelas serta tabel confidence dan koordinat.

Google Colab · OpenCV · Pemahaman konsep → pengamatan → praktikum → analisis

Mode belajar: tulis kode sendiri. Copy/cut, seleksi teks dan klik kanan dibatasi pada halaman; pembatasan UI bukan jaminan anti-penyalinan mutlak.

1. Tujuan

  1. Memilih kelas target dari model.names dan memvalidasi filter.
  2. Mengubah Results.boxes menjadi tabel koordinat dan confidence.
  3. Menghitung deteksi per kelas pada setiap gambar tanpa menebak jumlah objek.
  4. Membandingkan hitungan otomatis dengan hitungan manual dan menganalisis galat.

Prasyarat: Modul 10: instalasi Ultralytics, Results, bbox, confidence dan visualisasi BGR/RGB.

2. Materi Pembahasan

Count adalah deteksi pada satu gambar; bukan jumlah unik sepanjang video.
Count adalah deteksi pada satu gambar; bukan jumlah unik sepanjang video.

2.1 Counting dibangun di atas deteksi

Program penghitung objek bukan sekadar menampilkan gambar dengan kotak. Program perlu mendefinisikan kelas target, memilih kandidat yang memenuhi aturan, menghitungnya, lalu melaporkan hasil dengan konteks. Pada contoh kendaraan, target dapat berupa car, motorcycle, bus, dan truck jika nama tersebut tersedia pada model. Tidak semua alat transportasi atau bagian kendaraan menjadi kategori terpisah pada bobot pretrained.

Satu bbox yang lolos filter dihitung sebagai satu deteksi target pada satu gambar. Ini berbeda dari jumlah objek yang benar di dunia nyata. Objek yang sangat kecil, tertutup, kabur, atau berada di luar distribusi pelatihan dapat terlewat. Sebaliknya, pola latar dapat diprediksi sebagai kendaraan. Karena itu label laporan sebaiknya jumlah deteksi, bukan jumlah kendaraan pasti. Counting harus disertai pemeriksaan visual dan batasan.

2.2 Memilih kelas secara eksplisit

Pemetaan model.names menghubungkan ID numerik dengan nama kelas. Program membuat kamus kebalikannya agar mahasiswa memilih target dengan nama yang dapat dibaca. Langkah validasi menolak nama yang tidak tersedia dan daftar kosong. Untuk model custom, nama dan urutan mengikuti dataset training; jangan membawa asumsi ID dari model pretrained ke model tersebut.

Parameter classes pada predict menyaring keluaran ke ID target. Filter ini tidak melatih ulang model dan tidak menjadikan model lebih memahami kelas baru. Pilihan kelas harus sesuai tujuan program, misalnya person untuk menghitung orang atau kelompok kendaraan untuk menghitung lalu lintas dalam foto. Laporkan kelas yang dipilih agar pembaca mengetahui apakah sepeda, kereta, atau objek lain dikecualikan dari hitungan.

2.3 Dari tensor menjadi tabel yang transparan

Results.boxes menyediakan cls, conf, dan xyxy. Nilai tersebut dapat berada pada GPU, sehingga pemindahan ke CPU diperlukan sebelum diubah ke daftar Python untuk tabel. Setiap baris menyimpan identitas gambar, ID dan nama kelas, skor, serta koordinat bbox. Lebar dan tinggi dihitung dari perbedaan koordinat, bukan dari ukuran gambar keseluruhan.

Tabel rinci membantu memeriksa kesalahan yang sulit terlihat pada ringkasan. Contohnya, dua bbox dengan lokasi mirip mungkin merupakan kandidat berlebih, sementara bbox sangat kecil dapat berkaitan dengan objek jauh. Namun ukuran kotak tidak langsung berarti ukuran objek sebenarnya karena perspektif berbeda. Pertahankan kolom tabel walaupun tidak ada deteksi supaya analisis berikutnya tidak gagal karena skema kosong atau kolom yang hilang.

2.4 Confidence dan trade-off counting

Threshold confidence adalah keputusan operasional. Threshold tinggi dapat mengurangi kandidat keliru tetapi juga membuang objek benar yang sulit. Threshold rendah dapat memulihkan objek tersebut dengan risiko menambah false positive. Pengaruhnya tidak selalu monoton terhadap galat absolut counting karena kandidat benar dan salah dapat berubah bersamaan.

Bandingkan beberapa threshold pada gambar yang sama dan jangan mengubah filter kelas bersamaan jika ingin mengisolasi pengaruh confidence. Hitungan manual menjadi rujukan sederhana: catat objek target yang terlihat menurut kebijakan yang konsisten. Tentukan bagaimana memperlakukan objek terpotong, pantulan, gambar pada poster, dan objek sangat tertutup. Kebijakan anotasi yang tidak jelas akan menghasilkan perbandingan yang tidak adil meskipun programnya benar.

2.5 Evaluasi pada tingkat gambar dan objek

Galat hitungan dapat dinyatakan sebagai hitungan deteksi dikurangi hitungan manual. Nilai positif menunjukkan kelebihan hitungan dan nilai negatif menunjukkan kekurangan. Galat absolut menghilangkan tanda, tetapi angka nol tidak membuktikan semua deteksi benar: satu objek yang hilang dapat diimbangi oleh satu bbox palsu. Karena itu audit bbox dan hitungan harus dilakukan bersama.

Ringkasan antargambar berguna untuk membandingkan kondisi pencahayaan, kepadatan, dan ukuran objek. Menjumlahkan hitungan dari foto yang tumpang tindih tidak menghasilkan jumlah objek unik; kendaraan yang sama dapat muncul berulang. Praktikum ini membatasi kesimpulan pada tiap gambar. Sistem counting operasional juga memerlukan privasi, sumber gambar berizin, dan dokumentasi batasan agar angka tidak dipakai di luar kondisi pengujian yang telah dilakukan.

Video pembelajaran sesuai bab

Object Detection with Pre-trained Ultralytics YOLOv8 Model | Episode 1 — Ultralytics.

Fokus saat menonton: Ikuti inferensi pretrained YOLOv8 pada media, lalu hubungkan results.boxes dengan filter kelas dan hitungan per gambar.

Buka video di YouTube jika pemutar tidak tersedia

Video referensi berbahasa Inggris. Bila ada setup lokal, API atau versi model berbeda, pelajari konsepnya dan tetap gunakan alur Google Colab pada praktikum bab ini. Ketersediaan pemutar mengikuti YouTube, pemilik video dan jaringan.

Referensi dan sumber ilustrasi

Foto daun: Ανώνυμος Βικιπαιδιστής, Wikimedia Commons, CC BY 3.0; diubah ukuran/intensitas untuk ilustrasi. Foto bus: contoh aset Ultralytics. Foto astronaut: NASA melalui scikit-image. Panel diagram/simulasi ditandai pada caption; bukan hasil eksperimen yang dikarang. Hak penggunaan sumber tetap mengikuti sumber asli.

3. Praktikum Google Colab

Buka Google Colab

Buat notebook baru, simpan pada Drive milik sendiri, lalu isi identitas. Gunakan sel kode terpisah untuk setiap langkah dan jalankan berurutan dengan Shift + Enter. Tidak perlu mengunduh notebook contoh atau memasang Python lokal.

Identitas di bagian paling atas notebook: tambahkan sel Text/Markdown sebelum kode dan isi Nama serta NPM.
# Materi 11 — Pengolahan Citra
Nama: [Nama lengkap mahasiswa]
NPM: [NPM mahasiswa]
Kelas: [Kelas, jika diperlukan]
  1. Jalankan notebook baru dengan identitas, instalasi, model, dan upload gambar.
  2. Tentukan kelas target berdasarkan daftar model.names yang tercetak.
  3. Jalankan counting dan periksa tabel bbox serta tabel hitungan per gambar.
  4. Masukkan hitungan manual setelah melihat citra asli; dokumentasikan kebijakan objek terpotong atau tertutup.
  5. Ulangi threshold pada input yang sama dan bandingkan hitungan serta bbox, bukan skor saja.
  6. Simpan notebook dengan semua output dan analisis; bagikan satu tautan Viewer.

Sel 1 — Instalasi Ultralytics

Jalankan sebagai sel tersendiri di Colab; tidak perlu meng-upgrade NumPy. Catat versi paket di sel berikutnya.

%pip install -q ultralytics

Sel 2 — Model baseline dan direktori keluaran

Bobot yolov8n.pt diunduh saat pemuatan pertama. Ini baseline ringan, bukan pernyataan bahwa model ini yang terbaru. CPU dapat digunakan.

from pathlib import Path
import cv2, numpy as np, matplotlib.pyplot as plt
import torch, ultralytics
from ultralytics import YOLO
from google.colab import files
OUTPUT = Path('/content/hasil_yolo')
OUTPUT.mkdir(parents=True, exist_ok=True)
DEVICE = 0 if torch.cuda.is_available() else 'cpu'
model = YOLO('yolov8n.pt')
print('Ultralytics:', ultralytics.__version__, 'Device:', DEVICE)
print('Kelas model:', model.names)

Sel 3 — Upload dan validasi gambar

Pilih satu atau lebih gambar berizin. Batas contoh: 20 gambar, maksimum 20 MB per gambar dan 20 megapiksel. Upload notebook memakai memori; jangan unggah berkas raksasa.

uploaded = files.upload()
if not uploaded or len(uploaded) > 20:
    raise ValueError('Upload 1–20 gambar.')
images = []
for index, (name, content) in enumerate(uploaded.items()):
    if Path(name).suffix.lower() not in {'.jpg', '.jpeg', '.png'}:
        raise ValueError(f'Format tidak didukung: {name}')
    if not (0 < len(content) <= 20 * 1024**2):
        raise ValueError(f'Ukuran tidak valid: {name}')
    image = cv2.imdecode(np.frombuffer(content, np.uint8), cv2.IMREAD_COLOR)
    if image is None or image.shape[0] * image.shape[1] > 20_000_000:
        raise ValueError(f'Gambar gagal dibaca atau terlalu besar: {name}')
    images.append((f'{index:02}_{Path(name).stem}', image))
print('Gambar valid:', len(images))

Sel 4 — Pilih objek berdasarkan nama kelas model

Contoh menghitung kendaraan dalam gambar. Ubah TARGET_NAMES menjadi nama yang benar-benar ada di model.names, bukan indeks kelas tebakan.

TARGET_NAMES = ['car', 'motorcycle', 'bus', 'truck']
CONF = 0.35
if not (0 < CONF <= 1):
    raise ValueError('Confidence harus di rentang (0,1].')
name_to_id = {name: int(idx) for idx, name in model.names.items()}
unknown = set(TARGET_NAMES) - set(name_to_id)
if unknown or not TARGET_NAMES:
    raise ValueError(f'Nama kelas tidak valid: {unknown}; lihat model.names.')
TARGET_IDS = [name_to_id[name] for name in TARGET_NAMES]
print('Filter:', dict(zip(TARGET_NAMES, TARGET_IDS)))

Sel 5 — Deteksi, koordinat, dan counting per gambar

Filter class diterapkan saat predict; penghitung berasal dari bbox yang benar-benar dikembalikan. Deteksi nol tetap menghasilkan tabel dengan kolom yang konsisten.

import pandas as pd
from collections import Counter
from IPython.display import display
all_rows, count_rows = [], []
columns = ['gambar', 'class_id', 'class_name', 'confidence',
           'x1', 'y1', 'x2', 'y2', 'width_px', 'height_px']
for name, image in images:
    result = model.predict(image, conf=CONF, classes=TARGET_IDS,
                           device=DEVICE, imgsz=640, verbose=False)[0]
    counts = Counter()
    for box in result.boxes:
        class_id = int(box.cls.item())
        class_name = model.names[class_id]
        x1, y1, x2, y2 = box.xyxy[0].cpu().tolist()
        score = float(box.conf.item())
        counts[class_name] += 1
        all_rows.append(dict(gambar=name, class_id=class_id,
            class_name=class_name, confidence=score, x1=x1, y1=y1,
            x2=x2, y2=y2, width_px=x2-x1, height_px=y2-y1))
    count_rows.append({'gambar': name, **{n: counts[n] for n in TARGET_NAMES},
                       'total_deteksi_target': sum(counts.values())})
    annotated = result.plot()
    if not cv2.imwrite(str(OUTPUT / f'{name}_count.jpg'), annotated):
        raise IOError('Gagal menyimpan citra hasil.')
    plt.figure(figsize=(10, 7))
    plt.imshow(cv2.cvtColor(annotated, cv2.COLOR_BGR2RGB))
    plt.title(f'{name} — {dict(counts)}'); plt.axis('off'); plt.show()
detections = pd.DataFrame(all_rows, columns=columns)
count_table = pd.DataFrame(count_rows)
display(detections); display(count_table)
detections.to_csv(OUTPUT / 'bbox.csv', index=False)
count_table.to_csv(OUTPUT / 'counting.csv', index=False)

Sel 6 — Masukkan hitungan manual dan hitung galat

Isi saat prompt berdasarkan gambar asli dan kebijakan target yang sama. Nilai manual tidak disiapkan sebagai ground truth buatan.

manual_rows = []
for name, image in images:
    plt.figure(figsize=(9, 6))
    plt.imshow(cv2.cvtColor(image, cv2.COLOR_BGR2RGB))
    plt.title(f'Hitung manual: {name}'); plt.axis('off'); plt.show()
    raw = input(f'Jumlah manual objek target untuk {name}: ').strip()
    if not raw.isdigit():
        raise ValueError('Masukkan bilangan bulat nonnegatif.')
    manual_rows.append({'gambar': name, 'jumlah_manual': int(raw)})
audit = count_table.merge(pd.DataFrame(manual_rows), on='gambar', validate='one_to_one')
audit['galat'] = audit['total_deteksi_target'] - audit['jumlah_manual']
audit['galat_absolut'] = audit['galat'].abs()
display(audit)
print('Rata-rata galat absolut hitungan:', audit['galat_absolut'].mean())
audit.to_csv(OUTPUT / 'audit_counting.csv', index=False)

Jika terjadi error

Filter nama tidak dikenali.
Periksa model.names; gunakan nama persis dari model atau latih custom, bukan membuat ID baru.
Tabel counting menyatakan nol.
Nol adalah hasil sah. Cek objek terlihat, kelas target dan threshold tanpa menambah bbox manual sebagai hasil model.
Galat hitungan nol dianggap sempurna.
Periksa bbox satu per satu karena false positive dan false negative dapat saling meniadakan.

Runtime Colab dan file upload bersifat sementara. Simpan output penting pada notebook/Drive sebelum sesi berakhir. Jika runtime direset, jalankan ulang sel dari awal. Gunakan media berizin dan hindari unggahan data sensitif tanpa izin.

4. Tugas 11

Buat program menghitung kendaraan atau objek tertentu pada gambar, dengan class filter dan tabel hasil yang dapat diaudit.

Ketentuan pengerjaan

  1. Pilih kategori target yang tersedia dan jelaskan alasan pemilihannya.
  2. Gunakan sedikitnya 5 gambar berizin dengan variasi kepadatan atau kondisi.
  3. Tampilkan anotasi, tabel confidence/xyxy dan hitungan per kelas setiap gambar.
  4. Bandingkan dengan hitungan manual dan minimal dua threshold; jelaskan kesalahan bbox, bukan hanya total.
  5. Simpan counting.csv, bbox.csv dan audit dalam runtime serta tampilkan ringkasannya di notebook.
  6. Kumpulkan hanya SATU link Google Colab, output dan analisis terlihat, akses Viewer, Markdown Nama dan NPM di atas.

Pertanyaan analisis

  1. Apakah galat total nol menjamin semua bbox benar?
  2. Kondisi mana paling sering menyebabkan false negative?
  3. Bagaimana definisi kelas dan kebijakan hitungan manual memengaruhi evaluasi?
Identitas di bagian paling atas notebook: tambahkan sel Text/Markdown sebelum kode dan isi Nama serta NPM.
# Materi 11 — Pengolahan Citra
Nama: [Nama lengkap mahasiswa]
NPM: [NPM mahasiswa]
Kelas: [Kelas, jika diperlukan]

Pengumpulan

Kumpulkan satu link Google Colab saja. Nama dan NPM wajib berada pada sel Markdown paling atas. Sertakan kode, output yang tersimpan/terlihat serta analisis di notebook; tidak perlu mengumpulkan file .ipynb, ZIP, PDF atau screenshot terpisah.

  1. Jalankan sel dengan konfigurasi valid dan simpan notebook beserta output. Pastikan opsi menghilangkan output saat menyimpan tidak aktif untuk versi pengumpulan.
  2. Bagikan sebagai Viewer/Pelihat kepada dosen. Gunakan akses link jika diizinkan institusi; bila dibatasi, beri akses khusus akun dosen. Jangan memberi izin edit publik.
  3. Periksa akses dari akun penerima. Kirim URL notebook Colab, bukan folder Drive atau runtime sementara.
AspekBobotIndikator
Filter dan implementasi counting35%Pemetaan kelas benar dan jumlah dihitung dari keluaran nyata.
Tabel dan visualisasi25%BBox, confidence, koordinat dan hitungan jelas.
Evaluasi manual dan threshold30%Audit konsisten, minimal dua threshold dan analisis kesalahan.
Reproduksibilitas10%Input, parameter dan notebook Viewer lengkap.