12. ünite / 12
Video ve arka plan çıkarma: hareket, leke, iz ve sayım
VideoCapture döngüsü, kare farkı, kayan ortalama arka plan ve MOG2, maske temizliği, leke izleme ve çizgi sayacı.
Bu ünitenin sonunda
- Bir video döngüsü kurup kare başına süreyi ölçmek
- Kare farkı ile arka plan modeli arasındaki farkı açıklamak
- Kayan ortalama ve MOG2'nin öğrenme oranını ayarlamak
- Ön plan lekelerini en yakın komşuyla izleyip çizgiyi geçenleri bir kez saymak
Ders notları
Video, saniyede 25–60 karelik bir görüntü dizisidir; cv2.VideoCapture her read() çağrısında bir kare verir. Sabit bir kamerada hareket eden şeyleri bulmanın en ucuz yolu arka planı bilmek ve ondan farkı almaktır.
Kare farkı ve arka plan modeli
Kare farkı |ft − ft−1| hareketi bulur ama duran bir nesne hemen kaybolur ve tek renkli bir aracın yalnız ön ve arka kenarı çıkar. Kayan ortalama arka planı yavaşça öğrenir:
α küçükse arka plan yavaş uyum sağlar (park eden araç uzun süre ön planda kalır), büyükse yavaş giden nesne arka plana karışır. Seçici güncelleme, ön plan piksellerinde çok küçük α kullanır. MOG2 her piksel için birkaç Gauss'luk bir karışım tutar: sallanan yaprak gibi çok kipli arka planları ve gölgeleri (ayrı bir gri değerle) tanır.
Maskeden sayıma
- Maskeyi açma/kapama ile temizle, bağlı bileşenleri (lekeleri) bul, küçükleri at.
- İzleme: her lekeyi bir önceki karedeki en yakın ize bağla; eşleşmeyen leke yeni iz, birkaç kare görünmeyen iz silinir.
- Sayım: bir izin önceki ve şimdiki merkezi çizginin iki yanındaysa +1; her iz yalnız bir kez sayılır.
Bu hat Gerçek Hayat Demoları'ndaki trafik sayacıyla aynı fonksiyonları kullanır.
Oyun alanı
Arka plan çıkarma ve sayım
Kayan ortalama arka plan modeli; her karede |kare − arka plan| eşiklenir, morfolojiyle temizlenir, lekeler bulunur ve en yakın komşuyla izlenir. Sayım çizgisini geçen her iz bir kez sayılır.
Kendin dene
Trafik sahnesinde öğrenme oranını 0,002, 0,05 ve 0,3 yap ve araçların maskede nasıl göründüğünü karşılaştır. Seçici güncellemeyi kapatınca yavaş araçlara ne oluyor? Eşiği 10'a indir ve gürültüyü 15 yap: sayaç neden şaşıyor, morfolojiyle düzeltebiliyor musun? Bir dakikada iki yönde kaç araç geçtiğini yaz ve sahnedeki gerçek sayıyla karşılaştır.
Kod
import cv2
import numpy as np
cap = cv2.VideoCapture('trafik.mp4') # ya da 0: kamera
fps = cap.get(cv2.CAP_PROP_FPS) or 30
avg, prev = None, None
while True:
ok, frame = cap.read()
if not ok:
break # video bitti
gray = cv2.GaussianBlur(cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY), (5, 5), 0)
if avg is None:
avg, prev = gray.astype(np.float32), gray
continue
diff = cv2.absdiff(gray, prev) # kare farkı: yalnız hareketli kenarlar
cv2.accumulateWeighted(gray, avg, 0.02) # arka plan = kayan ortalama
fg = cv2.absdiff(gray, cv2.convertScaleAbs(avg))
_, mask = cv2.threshold(fg, 25, 255, cv2.THRESH_BINARY)
prev = gray
cv2.imshow('mask', mask)
if cv2.waitKey(int(1000 / fps)) & 0xFF == ord('q'):
break
cap.release()
cv2.destroyAllWindows()import cv2
import numpy as np
rng = np.random.default_rng(1)
H, W, LINE = 240, 320, 160 # sayım çizgisi x = 160
bg = np.full((H, W, 3), 90, np.uint8)
cars = [(-40 - 90 * i, 20 + 44 * i, 3 + i % 2) for i in range(5)] # (x, y, hız)
mog = cv2.createBackgroundSubtractorMOG2(history=100, varThreshold=25, detectShadows=False)
prev, count, last = {}, 0, None
for t in range(220):
frame = bg.copy()
for i, (x0, y, v) in enumerate(cars):
x = int(x0 + v * t)
cv2.rectangle(frame, (x, y), (x + 36, y + 22), (40, 160, 230), -1)
frame = cv2.add(frame, rng.integers(0, 12, frame.shape, dtype=np.uint8)) # sensör gürültüsü
fg = mog.apply(frame)
fg = cv2.morphologyEx(fg, cv2.MORPH_OPEN, np.ones((3, 3), np.uint8))
n, lab, stats, cent = cv2.connectedComponentsWithStats(fg)
now = {}
for k in range(1, n):
if stats[k, cv2.CC_STAT_AREA] < 300:
continue
cx, cy = cent[k]
lane = int(cy // 44) # basit izleme: şerit başına bir iz
if lane in prev and prev[lane] < LINE <= cx:
count += 1 # çizgiyi soldan sağa geçti
now[lane] = cx
prev = now
last = frame
print('sayılan araç:', count)
cv2.line(last, (LINE, 0), (LINE, H), (0, 0, 255), 2)
cv2.imwrite('cikti.png', np.hstack([last, cv2.cvtColor(fg, cv2.COLOR_GRAY2BGR)]))Sık yapılan hatalar
- Kameranın kendisi hareket ederken arka plan çıkarma kullanmak: tüm görüntü ön plan olur; önce görüntüyü sabitlemek (öznitelik + homografi) gerekir.
- Öğrenme oranını çok büyük seçmek: duran ya da yavaş nesneler birkaç saniyede arka plana karışır.
- Gölgeleri nesne saymak: MOG2'de detectShadows=True ile gölge 127 değerini alır; eşiği 200 yap.
- Aynı izi her karede yeniden saymak: iz başına "sayıldı" bayrağı tut.
Yazılım mühendisliği bağlantısı
Video işleme gerçek zamanlı bir sistemdir: gecikme bütçesi ve kare düşürme politikası tasarımın parçasıdır.
- Kare başına süreyi ölç, ortalamayı ve 99. yüzdeliği kaydet; 33 ms'yi aşan kareleri say.
- Kayıtlı bir test videosu ve beklenen sayım değeri tut; değişikliklerde sayımın ±1 içinde kaldığını CI'da sına (tarayıcıdaki sahne de bu yüzden tohumlu ve deterministiktir).
Kendini sına
Kayan ortalama arka planda α çok büyük seçilirse ne olur?
Kare farkı yönteminin tek renkli, büyük bir araçta sorunu nedir?
Çizgi sayacında bir aracın iki kez sayılmasını ne önler?
MOG2'nin kayan ortalamaya göre üstünlüğü nedir?
Bu üniteden sonra bitirme projesinde
- Demo ve rapor: Komut satırı aracı, performans ölçümü (G5), test tablosu, 5 dakikalık demo ve kısa rapor.