YOLO Computer Vision Project

Blood Cell Counter: Deteksi RBC, WBC, dan Platelet

Pada satu citra blood smear, model perlu menjawab dua pertanyaan: sel apa yang terlihat dan di mana posisinya. Project ini mengajak kita membangun jawabannya dengan YOLO, dari dataset BCCD sampai aplikasi web yang dapat dicoba langsung.

Coba AplikasiDownload Dataset
Hasil YOLO mendeteksi RBC, WBC, dan platelet pada citra mikroskop
Merah menunjukkan RBC, cyan menunjukkan WBC, dan ungu menunjukkan platelet. Label sengaja disembunyikan agar sel yang berdekatan tetap mudah dilihat.

Satu label untuk seluruh gambar tidak cukup jika tujuan kita adalah menghitung sel. Kita perlu mengetahui kelas dan lokasi setiap objek terlebih dahulu. Karena itu, Blood Cell Counter memakai YOLO, yaitu model object detection yang menghasilkan kelas, confidence, dan bounding box dalam satu proses inferensi.

Sebelum melanjutkan

Project ini dibuat untuk mempelajari computer vision. Hasil pada satu citra bukan pemeriksaan darah lengkap atau complete blood count (CBC), sehingga tidak boleh digunakan sebagai dasar diagnosis maupun keputusan medis.

Problem Framing

Apa yang sebenarnya ingin kita bangun?

Hal pertama adalah membedakan image classification dan object detection. Image classification memberi satu label untuk seluruh gambar, sedangkan YOLO dapat menemukan banyak sel sekaligus. Pendekatan kedua lebih sesuai karena satu citra blood smear berisi beberapa objek dengan posisi yang berbeda.

  • Input: satu citra blood smear berformat JPG atau PNG
  • Kelas: RBC, WBC, dan Platelets
  • Task: multi-class object detection dengan YOLO
  • Output: class_id, confidence, dan box [x1, y1, x2, y2]
  • Hasil akhir: visual bounding box dan jumlah objek untuk setiap kelas
Sample Data

Lihat perbedaan sebelum dan sesudah model bekerja.

Sebelum masuk ke kode, mari lihat bentuk hasilnya. Kedua panel memakai citra yang sama. Panel kanan menambahkan bounding box dari YOLO, sementara nilai confidence dapat dilihat ketika box disentuh atau diarahkan pada aplikasi.

Sampel citra mikroskop sel darah sebelum diproses YOLO
Input mentahCitra blood smear · 640 × 480
Sampel keluaran YOLO dengan bounding box RBC WBC dan platelet
Output YOLORBC WBC Platelets
Dataset

Mulai dari dataset BCCD.

Model hanya dapat mempelajari objek yang tersedia pada dataset. BCCD menyediakan 364 citra JPEG berukuran 640 × 480 dengan anotasi Pascal VOC XML. Ukurannya cukup ringan untuk eksperimen, tetapi distribusi kelasnya tidak seimbang. Oleh karena itu, pembagian data perlu menjaga agar WBC dan platelet tetap muncul pada data training dan validasi.

364Citra JPEG
4.155RBC
372WBC
361Platelets
BCCD_Dataset/
├── BCCD/JPEGImages/       # citra 640 × 480
├── BCCD/Annotations/      # Pascal VOC XML
└── BCCD/ImageSets/Main/   # daftar train/test
Hal yang perlu diperhatikan

RBC mencakup sekitar 85% anotasi. Jika kita hanya melihat jumlah prediksi yang benar secara keseluruhan, performa WBC dan platelet dapat tertutup oleh kelas mayoritas. Karena itu, precision, recall, dan AP perlu diperiksa untuk setiap kelas.

Data Preparation

Ubah anotasi Pascal VOC menjadi format YOLO.

BCCD menyimpan anotasi sebagai file XML, sedangkan proses training YOLO membutuhkan file teks. Setiap citra dipasangkan dengan satu file label bernama sama, kemudian setiap baris di dalamnya mewakili satu objek.

class_id  x_center  y_center  width  height
1         0.4219    0.5375    0.1906 0.2583

Normalisasi koordinat

x_center = ((xmin + xmax) / 2) / image_width, sedangkan lebar box adalah (xmax - xmin) / image_width. Rumus yang sama dipakai pada sumbu Y menggunakan tinggi citra.

path: /content/blood-cells
train: images/train
val: images/val
names:
  0: Platelets
  1: RBC
  2: WBC

Urutan kelas harus konsisten dari file label sampai aplikasi. Model pada project ini memakai Platelets = 0, RBC = 1, dan WBC = 2. Jika urutannya berubah, bounding box dapat benar tetapi nama kelasnya keliru.

YOLO Pipeline

Ikuti alur dari citra sampai jumlah sel.

Setelah data siap, proses inferensi dapat dibaca sebagai rangkaian yang sederhana. Citra diubah menjadi 320 × 320 dengan teknik letterbox, yaitu mempertahankan rasio gambar lalu menambahkan ruang kosong bila diperlukan. Setelah itu, kandidat objek diprediksi dan hasil yang bertumpuk atau terlalu lemah disaring sebelum dihitung.

  1. 01Baca citra
  2. 02Letterbox 320 × 320
  3. 03Prediksi box dan kelas
  4. 04Filter confidence
  5. 05Jalankan NMS
  6. 06Hitung per kelas
  7. 07Gambar hasil

YOLO memproses seluruh citra dalam satu forward pass. Model kemudian diekspor ke format ONNX dan disajikan melalui endpoint image detection AutoTrain agar dapat digunakan oleh aplikasi web.

Model Training

Mulai dari baseline yang sederhana.

Kita tidak perlu memulai dari konfigurasi yang besar. YOLOv8n cukup ringan untuk menjadi baseline, sehingga alur data dan evaluasi dapat diperiksa lebih dahulu. Setelah itu, parameter dapat disesuaikan dengan GPU, ukuran split, dan kurva validasi.

Python · Ultralytics
from ultralytics import YOLO

model = YOLO("yolov8n.pt")
model.train(
    data="blood-cells.yaml",
    epochs=80,
    imgsz=640,
    batch=16,
    patience=15,
    project="runs/blood-cell-yolo",
)

metrics = model.val()
model.export(format="onnx", imgsz=640)

Apa yang sebaiknya dibandingkan?

Catat augmentasi, ukuran input, learning rate, confidence threshold, dan IoU NMS untuk setiap eksperimen. Gunakan split validasi yang sama, karena perbandingan mAP tidak banyak berarti jika data evaluasinya ikut berubah.

Python

Hubungkan model dengan aplikasi.

Setelah model tersedia sebagai endpoint, aplikasi cukup mengirim satu citra. Contoh berikut memetakan class ID dari respons API, menyaring confidence minimal 25%, lalu menghitung jumlah objek untuk setiap kelas.

Python
from collections import Counter
import requests

API_URL = "https://api.autotrain.app/api/autotrain/jobs/35c30248-3bc5-4e69-80a2-b765c2eccdae/predict-image"
LABELS = {0: "Platelets", 1: "RBC", 2: "WBC"}

with open("blood-smear.jpg", "rb") as image:
    response = requests.post(
        API_URL,
        files={"file": ("blood-smear.jpg", image, "image/jpeg")},
        timeout=60,
    )

response.raise_for_status()
detections = response.json()["prediction"]["detections"]

visible = [item for item in detections if item["confidence"] >= 0.25]
counts = Counter(LABELS[item["class_id"]] for item in visible)

print("RBC:", counts["RBC"])
print("WBC:", counts["WBC"])
print("Platelets:", counts["Platelets"])

Apa arti setiap bagian respons?

class_id menunjukkan jenis sel, confidence menunjukkan tingkat keyakinan model, dan box menyimpan posisi objek dalam format [x1, y1, x2, y2]. Tiga informasi inilah yang digunakan untuk menggambar hasil dan membuat ringkasan jumlah sel.

Post-processing

Pahami perbedaan confidence threshold dan NMS.

Keduanya sama-sama menyaring hasil, tetapi tugasnya berbeda. Confidence threshold membuang prediksi yang keyakinannya terlalu rendah. Non-Maximum Suppression (NMS) kemudian membandingkan IoU antar-box dan menyisakan kandidat terbaik ketika beberapa prediksi mengarah pada objek yang sama.

Endpoint project ini memakai threshold awal 0,25 dan class-wise NMS dengan IoU 0,5. Artinya, NMS diterapkan secara terpisah pada setiap kelas. Setelah respons diterima, aplikasi dapat menaikkan threshold secara lokal. Coba geser dari 25% ke 50% dan amati objek mana yang lebih dahulu hilang. Dari sini, trade-off antara precision dan recall menjadi lebih mudah dipahami.

Evaluasi

Jangan menilai model dari satu angka saja.

Object detection perlu dinilai dari ketepatan lokasi, kelas, dan jumlah objek. Intersection over Union (IoU) mengukur tumpang tindih antara box prediksi dan anotasi. Precision menunjukkan seberapa banyak prediksi yang benar, sedangkan recall menunjukkan seberapa banyak objek anotasi yang berhasil ditemukan. Average Precision (AP) merangkum hubungan precision dan recall untuk satu kelas, kemudian mean Average Precision (mAP) merata-ratakannya.

  • Laporkan AP RBC, WBC, dan Platelets secara terpisah.
  • Gunakan mAP@0.5 sebagai baseline dan mAP@0.5:0.95 untuk evaluasi lokasi yang lebih ketat.
  • Bandingkan jumlah prediksi dengan ground truth per citra menggunakan Mean Absolute Error (MAE).
  • Periksa missed detection, duplicate box, dan kesalahan kelas secara visual.
Cara membaca angka model

Metadata model mencatat mAP@0.5 sebesar 0,7979 pada data evaluasinya. Angka ini membantu kita memahami eksperimen, tetapi tidak menjamin performa yang sama pada laboratorium, perangkat, atau pewarnaan citra lain.

Responsible AI

Di mana model dapat keliru?

Model belajar dari pola yang tersedia pada BCCD. Ketika kondisi citra baru berbeda dari data training, hasilnya juga dapat berubah. Beberapa hal berikut perlu diperiksa sebelum model digunakan pada eksperimen lain.

  • BCCD hanya berisi ratusan citra dan distribusi kelasnya tidak seimbang.
  • Sel bertumpuk, blur, perbedaan pewarnaan (stain), atau pencahayaan baru dapat menurunkan kualitas deteksi.
  • Preprocessing yang tidak konsisten dapat mengubah posisi atau proporsi objek.
  • Jumlah objek pada satu bidang pandang bukan hasil pemeriksaan CBC klinis.
  • Validasi eksternal dan review tenaga medis diperlukan sebelum penggunaan pada konteks klinis.
Coba sendiri

Lanjutkan dari hasil yang sudah kita pahami.

Mulai dari aplikasi untuk melihat hubungan antara citra, bounding box, confidence, dan jumlah objek. Jika ingin membangun ulang pipeline-nya, unduh BCCD lalu gunakan bagian training di atas sebagai baseline.