Bir trafik kamerası kaydındaki hareketli nesneleri arka plan çıkarma yöntemiyle bulan, kareler arasında takip eden, hızlarını piksel/saniye cinsinden hesaplayan ve yaya/taşıt olarak sınıflandıran bir görüntü işleme çalışması. İkinci aşamada yaya geçidi ve kaldırım bölgeleri tanımlanıp basit bir kural denetimi ekleniyor: geçitte yaya varken geçide giren taşıtlar ve taşıt yoluna inen yayalar kırmızıyla işaretleniyor.
Hazır bir nesne tanıma modeli (YOLO, Haar Cascade vb.) kullanılmadı; her şey klasik görüntü işleme adımlarıyla yapıldı.
Python 3.9 veya üstü gerekiyor.
git clone https://github.com/FaruksImageProcessing/TrackAndDetect.git
cd TrackAndDetect
pip install -r requirements.txt
İki betik var. vize.py yalnızca tespit, takip, hız ve sınıflandırma yapar;
proje.py bunun üstüne bölge kurallarını ekler.
python vize.py --video Train.mp4
python proje.py --video Test.mp4
Pencere açıldığında ESC ile çıkılıyor. Ortak seçenekler:
| Seçenek | Ne yapıyor |
|---|---|
--video DOSYA |
İşlenecek video (vize.py için Train.mp4, proje.py için Test.mp4) |
--kaydet DOSYA |
İşlenmiş kareleri bir mp4 dosyasına yazar |
--gosterme |
Pencere açmaz; ekransız makinede veya uzak bağlantıda çalışır |
--maske |
Hareket maskesini ayrı bir pencerede gösterir |
Video bitince toplam yaya ve taşıt sayısı ekrana yazılıyor.
Depoda iki örnek kayıt var:
Train.mp4— 1024x576, 25 fps, 631 kare (yaklaşık 25 saniye). Eşikler bunun üzerinde ayarlandı.Test.mp4— 1280x720, 29,97 fps, 2002 kare (yaklaşık 67 saniye).
Yaya geçidi ve kaldırım köşeleri koda gömülü değil, bolgeler.json içinde video
adına göre duruyor. Başka bir kayıtla denemek için o videonun adını dosyaya
ekleyip poligon köşelerini yazmak yeterli:
"kendi_videom.mp4": {
"cozunurluk": [1280, 720],
"yaya_gecitleri": [[[79, 526], [386, 200], [516, 242], [187, 622]]],
"kaldirimlar": []
}Koordinatlar videonun kendi çözünürlüğüne göre veriliyor, bu yüzden bir videonun bölgeleri başka çözünürlükteki bir videoda kullanılamıyor.
Gri tonlama. Takip için gereken tek bilgi pikselin ışık yoğunluğu, renk
bilgisi işi yavaşlatmaktan başka bir şey yapmıyor. Kareler
0,299R + 0,587G + 0,114B ile griye çevriliyor.
Arka plan çıkarma. Sabit bir arka plan görüntüsü yerine hareketli ortalama
tutuluyor: arka_plan = 0,01 * gri + 0,99 * arka_plan. Kare ile arka plan
arasındaki mutlak fark 50'yi geçen pikseller hareket kabul ediliyor. Bu sayede
gün içindeki ışık değişimi ve bir yerde duran araçlar zamanla arka plana
karışıyor.
Morfolojik kapama. Eşikleme sonrası maskede nesnelerin içinde delikler
kalıyor. 5x5 elips çekirdekle kapama (A•B = (A⊕B)⊖B) bu boşlukları dolduruyor,
tek tük gürültü piksellerini de temizliyor.
Kontur ve merkez. Maskedeki dış konturlardan alanı 500 pikselkareden büyük olanlar nesne sayılıyor, her birinin çevreleyen dikdörtgeni ve merkez noktası çıkarılıyor.
Eşleştirme ve hız. Önceki karedeki merkezlerle bu karedekiler arasında
scipy.spatial.distance.cdist ile mesafe matrisi kuruluyor, en yakın çiftten
başlanarak eşleştiriliyor. Eşleşen bir nesnenin aldığı yol kare süresine
bölünerek hızı piksel/saniye cinsinden bulunuyor.
Sınıflandırma. Alanı 2000'in altında ve yüksekliği genişliğinin yarısından
fazla olan nesneler yaya, alanı 5000'in üstünde ve hızı 10 px/s'yi geçenler
taşıt sayılıyor. İkisine de uymayanlar "Belirsiz" olarak işaretleniyor ve sayıma
girmiyor. Bütün eşikler takip.py dosyasının başında toplu duruyor:
| Eşik | Değer | Anlamı |
|---|---|---|
YAYA_ALANI |
2000 | Yaya sayılmak için azami alan |
TASIT_ALANI |
5000 | Taşıt sayılmak için asgari alan |
ENBOY_ORANI |
0,5 | Yaya sayılmak için asgari yükseklik/genişlik |
TASIT_HIZI |
10 | Taşıt sayılmak için asgari hız (px/s) |
AZAMI_ESLESME |
80 | İki kare arasında bir nesnenin atlayabileceği azami piksel |
KAYIP_SINIRI |
10 | Bu kadar kare görünmeyen nesnenin kaydı kapanıyor |
ASGARI_KARE |
5 | Sayıma girmek için görülmesi gereken kare sayısı |
Sayım. Bir nesnenin tipi kareden kareye değişebiliyor; kimi zaman yayanın gölgesi alanını büyütüyor, kimi zaman araç yavaşlayınca hız eşiğinin altına düşüyor. Bu yüzden sayım her karede değil, nesne görüş alanından çıkıp kaydı kapanırken bir kez yapılıyor ve ömrü boyunca en çok hangi tipe girdiyse o kabul ediliyor. Beş kareden az görünenler gürültü sayılıp atılıyor.
proje.py iki durumu ihlal kabul edip nesneyi kırmızı çerçeveye alıyor:
- Yaya geçidinde yaya varken aynı geçide giren taşıt.
- Yaya geçidi ve kaldırım dışında, yani taşıt yolunda yürüyen yaya.
Taşıt yolu ayrı bir poligon olarak tanımlanmadı; geçit ve kaldırım poligonlarının
dışında kalan her yer taşıt yolu kabul ediliyor. Nokta-poligon testi
cv2.pointPolygonTest ile yapılıyor.
Yöntem hazır bir tanıma modeli kullanmadığı için sonuçlar yaklaşık. Son
çalıştırmada proje.py Test.mp4 üzerinde 81 yaya ve 11 taşıt saydı, vize.py
Train.mp4 üzerinde 33 yaya ve 8 taşıt.
- Bir nesne ağaç, direk veya başka bir araç arkasında on kareden uzun süre kalırsa kaydı kapanıyor, tekrar göründüğünde yeni kimlik alıyor ve iki kez sayılıyor. Sayılar bu yüzden gerçek sayıdan yüksek çıkıyor.
- Yan yana yürüyen iki kişi tek kontur olarak birleşiyor ve alanı büyüdüğü için taşıt tarafına kayabiliyor.
- Uzun gölgeler nesnenin alanına ve en-boy oranına karışıyor.
- Hız piksel/saniye cinsinden; metre/saniyeye çevirmek için kameranın açısını ve yüksekliğini bilmek, yani bir homografi çıkarmak gerekiyor.
- Eşikler Train.mp4'e bakılarak elle ayarlandı. Farklı yükseklikteki bir kamerada
YAYA_ALANIveTASIT_ALANIdeğerlerinin yeniden ayarlanması gerekir.
Daha iyi sonuç için nesne tespitinde YOLO gibi bir model, hız tahmininde optik akış, eşleştirmede ise Kalman filtresi denenebilir.
takip.py tespit, takip ve sınıflandırma; iki betik de bunu kullanıyor
vize.py birinci aşama: tespit, takip, hız, sınıflandırma
proje.py ikinci aşama: bölge kuralları ve ihlal işaretleme
bolgeler.json video başına yaya geçidi ve kaldırım köşeleri
Train.mp4 1024x576, 25 fps örnek kayıt
Test.mp4 1280x720, 29,97 fps örnek kayıt
rapor.pdf proje raporu
diyagram.pdf işlem adımlarının akış şeması
requirements.txt numpy, opencv-python, scipy
MIT. Ayrıntılar için LICENSE dosyasına bakın.