Spaces:
Sleeping
Mimari — Hasarİ v2
Bu doküman ML pipeline'ın iç işleyişini, parça-merkezli çıktı reorganizasyonunu ve servisler arası kontratları açıklar.
1. ML Pipeline — Akıllı Hibrit Mimari
Pipeline iki YOLO26-seg modelini paralel koşturur, sonra akıllı eşleme ile her hasarı doğru parçaya atar.
Görüntü
│
├──► Quality check (blur, exposure, vehicle present)
│
├──► [Paralel] Hasar modeli (YOLO26-seg, 6 sınıf)
│ └─► damages: [{type, polygon, bbox, confidence}, ...]
│
├──► [Paralel] Parça modeli (YOLO26-seg, 23 sınıf)
│ └─► parts: [{name, polygon, bbox, confidence}, ...]
│
├──► Akıllı eşleme (IoU + intersection_ratio)
│ ├─ Hasar parçaya tam kaplı → tek parça
│ ├─ Hasar iki+ parçaya yayılıyor → multi-part flag + affected_parts
│ ├─ Düşük güven → is_low_confidence_match flag
│ └─ Parça bulunamadı → primary_part = "unknown"
│
├──► Şiddet sınıflandırma (ensemble)
│ ├─ Kural-tabanlı: maske alanı + hasar tipi + parça → hafif/orta/ağır
│ ├─ CNN classifier: hasar bölgesi crop → 3-sınıf
│ └─ Ensemble: ağırlıklı kombinasyon
│
├──► Maliyet motoru (kademeli lookup)
│ ├─ (parça, hasar_tipi, şiddet) → range
│ ├─ Aynı parçada çoklu hasar → en pahalı dominant
│ └─ Toplam aggregation
│
└──► Output formatter (parça-merkezli reorganizasyon)
└─► JSON: { parts: [...], summary, multi_part_damages, visualization_urls }
Neden paralel + IoU eşleme?
Alternatif 1 — Kaskad (parça → her parçada hasar):
- ✅ Daha az false positive (sadece parça içi tarama)
- ❌ Yavaş (her parça için ayrı inference)
- ❌ İki parçaya yayılan hasarda problem (kapı↔çamurluk arası çizik)
- ❌ Parça kaçırılırsa üzerindeki hasar da kaçar
Alternatif 2 — Naif paralel (her hasar en yakın parçaya):
- ✅ Hızlı, tek geçişte
- ❌ Yanlış parça eşleme riski
Seçim — Akıllı paralel:
- Paralel hızını korur
- IoU + intersection_ratio ile doğru eşleme yapar
- Multi-part hasarı ayrı işaretler (bilgi kaybı yok)
- Parça kaçırılsa bile hasar yine tespit edilir ("unknown" fallback)
IoU eşleme kuralları
# pseudocode — services/ml/pipeline.py
for damage in damages:
candidates = []
for part in parts:
iou = iou(damage.mask, part.mask)
intersection_ratio = intersection_area(damage.mask, part.mask) / damage.area
if intersection_ratio >= 0.5: # hasar parçanın yarısından fazla içindeyse
candidates.append((part, iou, intersection_ratio))
if not candidates:
damage.primary_part = "unknown"
elif len(candidates) == 1:
damage.primary_part = candidates[0][0].name
else:
# Birden fazla parça örtüşüyor → multi-part
candidates.sort(key=lambda c: -c[2]) # intersection_ratio'ya göre
damage.primary_part = candidates[0][0].name
damage.secondary_parts = [{"part": c[0].name, "ratio": c[2]} for c in candidates[1:]]
damage.is_multi_part = True
# Düşük güven kontrolü
if candidates and candidates[0][1] < 0.05:
damage.is_low_confidence_match = True
iou_threshold = 0.05 bilinçli olarak düşük — bilinmeyen parça > yanlış parça. Detaylar: services/ml/pipeline.py.
2. Parça-merkezli output reorganizasyonu
Pipeline iç düzeyde hasar-listesi tutar, ama API kullanıcısına parça-merkezli JSON döner. services/ml/output_formatter.py bu çeviriyi yapar.
İç (raw):
damages = [{id, type, primary_part, severity, cost, ...}, ...]
parts = [{name, polygon, confidence}, ...]
Dış (kullanıcıya):
parts = [
{
name, name_tr, status, # status: clean | minor | moderate | severe
damage_count,
damages: [...], # bu parçaya ait hasarlar
part_cost_min_tl, part_cost_max_tl,
cost_note, # "Tek parça değişimi diğer hasarları kapsar"
}
]
Kritik: hasarsız parçalar da listede, status: "clean" ile. Kullanıcı "kontrol edildi, hasar yok" güvencesi alıyor.
3. Şiddet ensemble
services/ml/severity_classifier.py üç katman:
- Kural-tabanlı (
RuleBasedSeverity):area_ratio < 0.005→ hafif0.005 ≤ area_ratio < 0.02→ ortaarea_ratio ≥ 0.02→ ağır- Hasar tipi çarpanları: glass_shatter → her zaman ≥ orta, scratch → genelde hafif
- CNN classifier (
CNNSeverity):- EfficientNetV2-S, hasar crop'u → 3-sınıf softmax
- Roboflow severity setinde fine-tune edilir
- Ensemble (
EnsembleSeverity):- Anlaşıyorlarsa → o seviye, yüksek güven
- Anlaşmıyorlarsa → ağırlıklı (kural %40, CNN %60), düşük güven flag
v1'de kural-tabanlı yeter (açıklanabilir, sigortacı için satılabilir). CNN v2 backlog.
4. Maliyet motoru — kademeli lookup
services/ml/cost_engine.py + cost_table.yaml (TR-specific).
Lookup hiyerarşisi: (parça, tip, şiddet) → (parça, tip default) → (global default) → hard default. Her seviye düştükçe cost_confidence düşer (high → medium → low).
Çoklu hasar aggregation: Aynı parçada birden fazla hasar varsa, naif toplam yanlış olur (parça değişimi diğer hasarları zaten kapsar). En pahalı %70'i aşıyorsa, sadece o alınır + cost_note: "Tek parça değişimi diğer hasarları kapsar".
v1 sınırlamaları:
- Lookup tablosu manuel — TR pazar verileriyle güncellenmeli (otoyedek, yetkili servisler, TSB)
- Araç modeline duyarlı değil (Fiat Egea vs. BMW 5 farkı yok) — v2 backlog
- İşçilik vs. parça ayrı satır değil — agregate range
5. Servisler arası kontratlar
Backend ↔ Frontend (TypeScript)
packages/types/src/ altında Pydantic şemalarının birebir TS karşılığı. Web, desktop ve mobile aynı tipleri kullanır.
| Backend (Pydantic) | Frontend (TS) | Yer |
|---|---|---|
models.Damage |
Damage |
packages/types/src/damage.ts |
models.Part |
Part |
packages/types/src/part.ts |
models.Inspection |
Inspection |
packages/types/src/inspection.ts |
models.InspectionSummary |
InspectionSummary |
packages/types/src/inspection.ts |
models.HealthResponse |
HealthResponse |
packages/types/src/api.ts |
Senkron tutmak için: python services/backend/scripts/export_openapi.py çalıştırıp packages/types/openapi.json üretilir, manuel karşılaştırma yapılır. (v0.2'de openapi-typescript ile otomatik gen düşünülebilir.)
Frontend (UI paylaşımı)
packages/ui web ve desktop tarafından doğrudan import edilir. Mobile (RN) React DOM yerine RN component'leri kullandığından packages/ui'yi DOĞRUDAN kullanmaz — apps/mobile/components/ altında benzer component'ler RN-native olarak yaşar. Hedef: aynı API yüzeyini koru, render farklı.
ML ↔ Backend
ML pipeline (services/ml/pipeline.py) Python class olarak çağrılır:
pipeline = DamagePipeline(damage_weights="...", parts_weights="...", ...)
result = pipeline.run(image_path) # dict, packages/types ile uyumlu
Backend services/backend/ml_service.py singleton wrapper'ı tutar (model yükleme tek sefer, request başına inference). Celery worker (worker.py) async job için bu singleton'ı yeniden kullanır.
6. Veri akışı — uçtan uca
Kullanıcı (Web/Desktop/Mobile)
│
│ multipart POST /api/v1/inspect
▼
FastAPI
├─ S3/MinIO'ya orijinal görüntü yükle
├─ Postgres'e inspection kaydı (status=queued)
├─ Celery task'ı kuyruğa koy
└─ {inspection_id, status_url} döndür
│
▼
Celery Worker (Redis broker)
├─ S3'ten görüntü çek
├─ ML Pipeline (singleton, warm)
│ ├─ paralel hasar + parça inference
│ ├─ IoU eşleme, severity, cost
│ └─ visualization.py: 3 PNG üret (annotated, parts, damages)
├─ Postgres'e sonuç + status=completed
├─ S3'e visualization PNG'leri
└─ Redis pub/sub: status push
│
▼
Frontend
├─ Polling: GET /api/v1/inspect/{id} (2sn aralık)
│ veya WS /api/v1/inspect/{id}/stream
└─ status=completed → result JSON + visualization URL'leri
7. Performans hedefleri
| Senaryo | Hedef latency | Notlar |
|---|---|---|
| Sync tek görüntü (cloud GPU, T4) | < 2sn | YOLO26-m batch=1 |
| Async 5 görüntü | < 8sn | paralel inference |
| Async 30 görüntü (360° tarama) | < 30sn | Celery 4-worker |
| Mobile on-device QC | < 100ms | YOLO26-n TFLite |
| Cold start (model load) | < 8sn | singleton ile bir kere |
Yerel dev (RTX 5050 8GB): batch=8 m-model ~30ms/image. Production GPU (T4) benzer.
8. Gözlemlenebilirlik (v0.2)
- Sentry — frontend ve backend hataları
- Prometheus — request latency, inference time, queue depth, error rate
- Grafana —
observability/altında dashboard JSON - Structured logs — backend loguru JSON, frontend pino (browser)
- Trace ID — her inspection için, headers ve log'larda
9. Güvenlik
- Auth: v1 API key (
X-API-Key), v2 JWT - CORS:
localhost:3000(web dev),tauri://localhost(desktop prod), Expo emülatör. Production'da env'den whitelist. - CSP: Tauri config'te sıkı, sadece localhost+https.
- PII: Plaka/VIN ham görüntüde — anonimleştirme v0.2.
- Rate limit: v0.2, Redis-based.
10. Bilinçli kısıtlamalar
- CarDD academic non-commercial — ticari pilot için ayrı izin gerekli, ya da kendi etiketli veri seti.
- Türk araç modelleri zayıf temsil — pilot'tan 500-1000 TR görüntüyü etiketleyip fine-tune (Hafta 11-12).
- Aydınlatma/açı edge case'leri — capture flow'da rehberlik, yine de %20-30 başarısız case kaçınılmaz.
- Maliyet tablosu manuel — TR pazar verisiyle güncellenmeli, otomatik scraping v2.