C++ ve LibTorch ile sıfırdan tasarlanmış, hazır/önceden eğitilmiş model kullanmayan bir CNN ile drone görüntülerinde araç tespiti.
Bu proje, akıllı kavşak sistemleri için drone görüntülerinden araç tespiti yapan, tamamen özgün (hazır mimari veya önceden eğitilmiş ağırlık kullanmayan) bir evrişimli sinir ağı (CNN) içerir. Model C++ dilinde, LibTorch (PyTorch'un C++ API'si) ile yazılmıştır — LibTorch yalnızca tensör işlemleri ve otomatik türev (autograd) altyapısı sağlar; mimari, katman sayısı, filtre boyutları gibi tüm tasarım kararları özgündür.
İki açık veri seti birleştirilerek 43.826 görüntülük bir eğitim seti oluşturulmuştur:
- AU-AIR (32.823 görüntü) — gerçek kavşak sahnesi, 8 sınıf (Human, Car, Truck, Van, Motorbike, Bicycle, Bus, Trailer)
- UAVDT (11.003 görüntü) — gece dahil çeşitli ışık koşulları, 3 sınıf (car, truck, bus)
İki veri setinin sınıf numaralandırmaları eşleştirilmiş, YOLO formatında (class x_center y_center width height, normalize) birleştirilmiştir. Detaylar için scripts/ klasörüne bakınız.
- Girdi: 416×416×3 RGB görüntü
- Backbone: 5 konvolüsyon bloğu (Conv2d → BatchNorm → ReLU → MaxPool), filtre sayısı 16→32→64→128→256
- Tespit kafası: 1×1 konvolüsyon, 13×13 ızgara, hücre başına 2 anchor (küçük/büyük araç oranı), anchor başına 13 değer (1 objectness + 4 bbox + 8 sınıf) — toplam 26 kanal
- Toplam parametre: 400.282
- Loss: Objectness (BCEWithLogitsLoss), Bbox (MSE), Sınıflandırma (sınıf ağırlıklı CrossEntropyLoss), ağırlıklı toplam
- Veri artırma: %50 olasılıkla yatay çevirme (görüntü + etiket birlikte)
Detaylı mimari gerekçeleri için src/vehicle_detector.h içindeki yorumlara bakınız.
İlk sürümde her ızgara hücresi yalnızca TEK bir araç önerebiliyordu; aynı hücreye düşen farklı boyuttaki araçlar (örn. bir motosiklet + arkasındaki kamyon) birbirinin üzerine yazılıyor, ayrıca komşu hücrelerin aynı aracı tekrar tekrar işaretlemesi yanlış pozitif oranını artırıyordu. v2'de hücre başına 2 anchor (küçük/büyük araç) eklenerek bu sınırlama önemli ölçüde giderildi. Ayrıca eğitim setinde Car sınıfının tek başına %87 olmasından kaynaklanan sınıf karışıklığını azaltmak için ağırlıklı loss, ve genelleme için veri artırma eklendi.
Model, Google Colab üzerinde GPU ile eğitilmiştir. v1 (anchor'sız) 30 epoch eğitilmiş, doğrulama kaybı 15. epoch'ta en düşük seviyeye ulaşıp sonrasında aşırı öğrenmeye (overfitting) girdiği için 15. epoch checkpoint'i seçilmişti. v2 (anchor'lı, ağırlıklı loss + veri artırmalı) mimari değişikliği nedeniyle sıfırdan eğitilmiş ve tam 30 epoch tamamlanmıştır.
| Epoch | Train Loss (v1) | Val Loss (v1) |
|---|---|---|
| 5 | 0.631 | 0.775 |
| 10 | 0.458 | 0.578 |
| 15 | 0.355 | 0.562 ← v1 için seçilen |
| 20 | 0.284 | 0.613 |
| 30 | 0.218 | 0.730 |
| Metrik | v1 (anchor'sız, epoch 15) | v2 (anchor'lı, epoch 30) |
|---|---|---|
| mAP@0.5 | 0.085 | 0.144 (+69%) |
| Ortalama IoU (eşleşen tahminler) | 0.622 | 0.635 |
Sınıf bazında AP (v2): Bus 0.323, Truck 0.227, Car 0.214, Van 0.156, Human 0.108, Motorbike 0.065, Trailer 0.029, Bicycle 0.027 — en sık görülen sınıflarda (Car, Truck, Bus) belirgin iyileşme var; örneklem sayısı çok düşük olan sınıflarda (Motorbike: 40 GT, Bicycle: 148 GT) hâlâ zorlanıyor.
Not: mAP hâlâ literatür standartlarının altında — bunun nedeni artık "hücre başına tek tahmin" sınırlaması değil (anchor ile kısmen çözüldü), daha çok modelin küçük kapasitesi (400K parametre) ve nispeten kısa eğitim süresi. Kalan sınırlamalar için aşağıdaki bölüme bakınız.
src/ C++ kaynak kodları (mimari, veri yükleyici, loss, eğitim, çıkarım, değerlendirme)
scripts/ Python veri hazırlama scriptleri
demo_app/ Masaüstü demo arayüzü (Python/Tkinter) + schema.sql (PostgreSQL şeması)
CMakeLists.txt Örnek derleme yapılandırması
- C++17 destekli derleyici (g++ 11+)
- CMake 3.18+
- LibTorch (CPU veya CUDA sürümü)
- OpenCV 4.x (
libopencv-dev)
mkdir build && cd build
cmake -DCMAKE_PREFIX_PATH=/path/to/libtorch ..
cmake --build . --config Release./inference <model_checkpoint.pt> <goruntu.jpg> <cikti.jpg> <guven_esigi>
# örnek:
./inference model_epoch30.pt test.jpg sonuc.jpg 0.7cd demo_app
pip install pillow --break-system-packages
python3 app.pySistemin tek bir fotoğraf üzerinde çalışan bir demo olmaktan çıkıp çok noktalı bir kavşak izleme altyapısına dönüşebilmesi için, demo uygulamasına PostgreSQL tabanlı bir kayıt katmanı eklenmiştir. Her tespit; hangi kameradan geldiği, hangi modelle çalıştırıldığı ve sonuçlarıyla birlikte kalıcı olarak saklanır.
Çoklu kamera senaryosunda birden fazla kaynaktan eşzamanlı yazma söz konusu olacağından, dosya tabanlı/tek yazarlı bir çözüm (SQLite) yerine ilişkisel bütünlüğü (foreign key), eşzamanlılık kontrolünü ve kurumsal ortamlarda yaygın kullanımı sağlayan PostgreSQL tercih edilmiştir.
Üç tablodan oluşan, normalize edilmiş bir yapı (bkz. demo_app/schema.sql):
| Tablo | İçerik |
|---|---|
cameras |
Kamera tanımları (code, label, description) — şu an 4 sabit kamera (cam1–cam4) tanımlı |
detection_runs |
Her "Tespiti Çalıştır" işlemi: kamera (FK), model, güven eşiği, görsel yolları, toplam araç sayısı, ortalama güven, işlem süresi, yoğunluk skoru/seviyesi, zaman damgası |
detected_vehicles |
Bir çalıştırmada tespit edilen her aracın kendi satırı: sınıf ve o araca özgü güven skoru (run_id FK, ON DELETE CASCADE) |
Bu yapı; "belirli bir kamerada, belirli bir zaman aralığında hangi sınıftan kaç araç tespit edildi" gibi sorguların doğrudan SQL ile yanıtlanabilmesini sağlar — trafik yoğunluğu raporlaması gibi ileri analizlerin temelini oluşturur.
- Kamera seçici: Model seçiminin yanına eklenen Kamera 1–4 seçeneği.
Şu an fiziksel bir kamera bağlantısı yok; operatör hangi noktadan gelen
görüntüyü işlediğini bu şekilde etiketliyor. Gerçek kamera/RTSP akışına
geçildiğinde yalnızca
camerastablosuna kaynak bilgisi eklenir, arayüz ve veritabanı şeması değişmeden kalır. - Otomatik kayıt: Her başarılı tespit, seçili kameraya bağlı olarak otomatik şekilde veritabanına yazılır — ek bir işlem gerekmez.
- Kayıtlar penceresi: Geçmiş tüm tespitleri (zaman, kamera, model, eşik, toplam araç, ortalama güven, yoğunluk, süre) listeleyen, kameraya göre filtrelenebilen ayrı bir görünüm. Üst kısımda, seçilen filtreye göre canlı hesaplanan özet kartları var: toplam kayıt, toplam araç, en sık görülen sınıf, ortalama yoğunluk skoru — doğrudan SQL agregasyon sorgularından besleniyor.
- Sistem durumu göstergesi: Ana ekranın sağ üstünde, veritabanına gerçekten bağlanılabildiğini gösteren canlı bir durum etiketi bulunur.
Veritabanına yazma işlemi başarısız olursa (Postgres kapalı, farklı bir makinede kurulu değil, vb.) tespit özelliği bundan etkilenmez — kullanıcıya bir uyarı gösterilir, ancak uygulama akışı kesilmez. Bu sayede demo, veritabanı kurulumu olmayan bir ortamda da tam işlevsel şekilde çalışmaya devam eder.
Bağlantı bilgileri koda gömülü değil, ortam değişkenleri üzerinden
yönetilir (KAVSAK_DB_NAME, KAVSAK_DB_HOST, KAVSAK_DB_USER,
KAVSAK_DB_PASSWORD). Varsayılan yapılandırma yerel Unix socket üzerinden
şifresiz (peer authentication) bağlanır; gerçek bir sunucuya taşınırken
kod değişikliği gerekmez, yalnızca ortam değişkenleri güncellenir.
createdb kavsak_tespit
psql -d kavsak_tespit -f demo_app/schema.sql
pip install psycopg2-binaryModel checkpoint dosyaları (.pt) boyut nedeniyle bu repoda yer almamaktadır. Google Drive linki için proje sahibiyle iletişime geçiniz.
Hücre başına tek tahmin sınırlaması— v2'de 2 anchor eklenerek giderildiSınıf dengesizliği— v2'de ağırlıklı loss ve veri artırma ile kısmen giderildi- Küçük model kapasitesi (400K parametre) — ince sınıf ayrımlarında (örn. Car/Truck) ve az örnekli sınıflarda (Motorbike, Bicycle) hâlâ geliştirmeye açık
- Sabit, elle seçilmiş anchor boyutları — veri setindeki gerçek kutu boyutları üzerinden k-means ile otomatik anchor seçimi (YOLOv2 tarzı) daha isabetli anchor'lar üretebilir
- Tek görüntü/parça başına tek forward pass — büyük görüntülerde
inference.cpp'deki parça tabanlı (tiled) çıkarım hesaplama maliyetini artırıyor, gerçek zamanlı (video) kullanım için optimizasyon gerekir