Pređi na sadržaj
Vuk Cvetković
Projekti

Uporedni sistem za detekciju objekata

Ista slika kroz dva ekosistema mašinskog učenja, sa odgovorom u jednom formatu.

Godina
2026
Kontekst
Master rad, Elektronski fakultet u Nišu
Domen
Lična zaštitna oprema na gradilištu

Kako prolazi jedan zahtev

  1. Ulaz: React frontend - React
  2. Slika, multipart/form-data
  3. Orkestracija: NestJS gateway - NestJS
  4. Paralelno
    • FastAPI servis - Ultralytics YOLOv8m - Python, FastAPI
    • ASP.NET Core servis - ML.NET model - C#, ASP.NET Core
  5. Jedan JSON format: okviri, klase, pouzdanost

Demo

Pregled

Rad istražuje šta se menja kada se isti zadatak detekcije napravi dva puta: jednom u Python-u, koji je standard u istraživanju, i jednom u .NET-u, na kom već radi backend. Sistem obučava YOLOv8m i ML.NET model na istim anotiranim slikama, stavlja oba iza jednog API-ja i pušta sliku kroz jedan ili kroz oba.

Domen je lična zaštitna oprema na gradilištu, sa šest klasa: šlem, prsluk i rukavice, svaka kao prisutna ili odsutna. Ključne su negativne klase: sistem je koristan samo ako može da kaže da neko ne nosi šlem, a ne samo da se šlem nalazi negde u kadru.

Tehnologije

Frontend
React
Gateway
NestJS
Python servis
Python
FastAPI
Ultralytics
PyTorch
OpenCV
NumPy
.NET servis
ASP.NET Core
C#
ML.NET
Skup podataka
Roboflow

Arhitektura

  1. Frontend šalje sliku

    React šalje fajl kao multipart/form-data, a izabrani model ide u posebnom polju. Kada se traže oba, dva zahteva idu paralelno, pa se modeli porede na istoj slici u istom trenutku.

  2. Gateway prosleđuje zahtev

    NestJS je jedina adresa koju frontend poznaje. Prima upload i prosleđuje ga FastAPI ili ASP.NET Core servisu, pa se ML servisi mogu menjati nezavisno od klijenta.

  3. Servis radi inferenciju

    Python učitava sliku u RGB i predaje je YOLOv8m modelu. Težine modela ostaju učitane u memoriji, pa se .pt fajl ne čita pri svakom zahtevu. .NET strana pretvara sliku u MLImage i bira ML.NET model po id-u.

  4. Oba servisa vraćaju isti format

    Klasa, score i okvir kao x1, y1, x2, y2, uz id modela, skup anotacija na kom je obučen i originalne dimenzije slike. .NET strana prvo ograničava koordinate na te dimenzije, pa okvir nikad ne izlazi van slike.

  5. Frontend iscrtava rezultat

    Pošto je odgovor isti u oba slučaja, interfejs nema posebnu granu ni za YOLO ni za ML.NET. Koordinate se skaliraju sa originalne na prikazanu veličinu, a okviri, klase i pouzdanosti se iscrtavaju preko slike.

Šta radi

  • Jedan model ili oba

    Jedan servis ili oba istovremeno, u dva panela nad istom slikom, uz izbor bilo kog od četiri obučena modela.

  • Podesiv prag pouzdanosti

    Slajder skriva sve ispod praga, kao što i pravi sistem reaguje samo na predikcije iznad granice, a ne na sve što model vrati.

  • Lista svih detekcija

    Klasa i score za svaku detekciju. Kada se jedna izabere, izdvaja se na slici, što pomaže kada se u kadru preklapa osam okvira.

  • Okviri, ispuna, zoom i pan

    Okviri kao linije ili kao ispunjene površine, jedna detekcija ili sve, uz zoom i pan da se okvir uporedi sa pikselima ispod njega.

  • Dva odgovora uporedo

    Trajanje zahteva, broj detekcija, prosečna pouzdanost, najjača detekcija i koji servis je prvi odgovorio.

  • Provera stanja servisa

    Gateway, Python API i .NET API javljaju status i vreme odgovora. To su tri odvojena procesa, pa kada jedan ne radi, interfejs pokazuje koji.

Skup podataka i obučavanje

Skup podataka je sastavljen u Roboflow-u od dva javna skupa, koje sam pregledao i spojio u jedan: 2.911 slika, od čega 2.374 za trening, 290 za validaciju i 247 za test, automatski orijentisanih i svedenih na 640x640. Python strana ga koristi u YOLO formatu, a .NET strana u COCO formatu, jer Model Builder za detekciju očekuje COCO. Tako oba alata dobijaju svoj format, nad istim slikama i istim klasama.

Onda je došao deo koji nisam planirao. Prva verzija je imala 8.813 anotacija, a posle ponovnog pregleda taj broj je narastao na 17.942, što znači da više od polovine objekata nije bilo označeno. Objekat koji postoji na slici, a nema ga u oznakama, tokom obučavanja uči model da je to pozadina, a tokom evaluacije mu se računa kao greška kada ga model ipak detektuje.

Oba modela su obučavana 50 epoha na 640x640, polazeći od unapred obučenih težina, sa istim parametrima za obe verzije skupa, da bi razlika u rezultatima poticala od kvaliteta anotacija, a ne od konfiguracije. Model Builder se zaustavlja na obučenom modelu, pa je za .NET stranu trebao poseban servis za evaluaciju: učitava COCO anotacije, radi predikciju nad validacionim skupom i računa precision, recall, F1 i mAP@0.5, uz matrice konfuzije i precision-recall krive. Tako ML.NET dobija iste metrike koje Ultralytics prikazuje sam.

Rezultati

Uporedni sistem za detekciju objekata - Rezultati
ModelAnotacijePrecisionRecallF1mAP@0.5mAP@0.5:0.95
YOLOv8m8.8130,7380,800-0,7900,455
YOLOv8m17.9420,8940,867-0,9160,552
ML.NET8.8130,6690,6450,6570,580-
ML.NET17.9420,8620,7090,7780,748-

Ponovno anotiranje popravilo je svaku metriku kod oba modela. YOLOv8m je porastao sa 0,790 na 0,916 mAP@0.5, a ML.NET sa 0,580 na 0,748, pa je slabiji model relativno dobio više, 29 procenata prema 16. Loše anotacije su njega najviše i kočile.

YOLOv8m je ispred po brojevima, a najvažnija razlika je u recall-u: 0,867 prema 0,709 na ispravljenom skupu, uz skoro isti precision. Kod zaštitne opreme to je presudno, jer propuštena detekcija znači da sistem čoveka bez opreme prijavi kao ispravno opremljenog, a precision to ne može da pokaže.

Poređenje je fer jer su uslovi bili isti na obe strane: isti domen slika, istih šest klasa i uporedivi parametri, bez posebnog podešavanja za svaki model.

Šta sam naučio

Na rezultat su više uticali podaci nego izbor frameworka. Ponovno anotiranje istih 2.911 slika popravilo je oba modela više nego što iznosi razlika između dva ekosistema, i to nije zaključak koji sam očekivao.

Sa inženjerske strane, zaključci su praktičniji. Python je dao prostor za eksperimentisanje i sam generisao materijal za evaluaciju, .NET je dao model koji se direktno uklapa u ASP.NET Core servis, a zajednički format odgovora omogućava da jedan frontend radi sa oba modela bez ikakve razlike.

Svi projekti

Esc