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.
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.
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
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.

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.
BCCD_Dataset/ ├── BCCD/JPEGImages/ # citra 640 × 480 ├── BCCD/Annotations/ # Pascal VOC XML └── BCCD/ImageSets/Main/ # daftar train/test
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.
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.
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.
- 01Baca citra
- 02Letterbox 320 × 320
- 03Prediksi box dan kelas
- 04Filter confidence
- 05Jalankan NMS
- 06Hitung per kelas
- 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.
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.
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.
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.
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.
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.
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.
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.
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.
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.