Okullar için Robotik ve Mühendislik · anaokulundan liseye

4. ünite / 12

Evrişim ve filtreler: bulanıklaştırma, keskinleştirme, gürültü

Çekirdek, kenar koşulu, kutu ve Gauss bulanıklığı, medyan filtre, keskinleştirme; PSNR ile ölçüm.

Bu ünitenin sonunda

  • 3×3 bir evrişimi elle hesaplamak
  • Kutu, Gauss ve medyan filtrelerini gürültü türüne göre seçmek
  • Keskinleştirme çekirdeğinin neden toplamı 1 olan bir çekirdek olduğunu açıklamak
  • Filtre sonucunu PSNR ile sayısal olarak karşılaştırmak

Ders notları

Komşuluk işlemlerinde yeni değer, pikselin çevresine de bakar. Bunun en genel biçimi evrişimdir: küçük bir ağırlık tablosu (çekirdek) görüntü üstünde kayar, her konumda ağırlıklı toplam alınır.

g(x, y) = Σi,j k(i, j) · f(x + i, y + j)

OpenCV'nin filter2D'si çekirdeği çevirmez (matematikte buna korelasyon denir); simetrik çekirdeklerde fark yoktur. Görüntünün kenarında komşu eksik kalır: OpenCV varsayılan olarak BORDER_REFLECT_101 ile yansıtır.

Bulanıklaştırma ailesi

  • Kutu: tüm ağırlıklar eşit (1/9). Hızlı ama kenarları kare biçimli yayar.
  • Gauss: ağırlıklar merkezden uzaklaştıkça azalır; ayrılabilir olduğundan iki 1B geçişle yapılır. Gauss gürültüsü için iyidir.
  • Medyan: doğrusal değildir, komşuların ortancasını alır. Tuz-biber gürültüsünü siler, kenarları korur.

Keskinleştirme

[0 −1 0; −1 5 −1; 0 −1 0] çekirdeği "orijinal + (orijinal − komşu ortalaması)" demektir. Ağırlıkların toplamı 1 olduğu için düz bölgeler değişmez, ayrıntı güçlenir; gürültü de güçlenir. Ölçmek için PSNR (tepe sinyal/gürültü oranı, dB) kullanılır: temiz görüntüye ne kadar yakın, o kadar yüksek.

Oyun alanı

Evrişim ve filtreler

Bir çekirdek görüntü üstünde kayar, her konumda ağırlıklı toplam alır. Gürültü ekle (tuz-biber ya da Gauss) ve kutu, Gauss, medyan ve keskinleştirme filtrelerini karşılaştır. Çekirdeğin sayıları sağda.

Önce: gürültülü
Sonra: filtreli
PSNR gürültülü: 17.3 dB PSNR filtreli: 35.3 dB

Kendin dene

Renkli şekillere %8 tuz-biber gürültüsü ekle. Kutu, Gauss ve medyanı 3 ve 5 boyutlarıyla dene ve PSNR'leri bir tabloya yaz. Hangisi kazandı, neden? Sonra gürültüyü Gauss'a çevir ve tabloyu tekrarla. Son olarak gürültüsüz görüntüde keskinleştirmeyi aç ve çekirdekteki sayıları toplayarak düz bölgelerin neden değişmediğini doğrula.

Kod

Python: evrişimi elle hesapla ve filter2D ile karşılaştır
import cv2
import numpy as np

img = cv2.imread('girdi.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY).astype(np.float32)
k = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]], np.float32)   # keskinleştirme

def conv3(f, k):
    p = np.pad(f, 1, mode='reflect')              # kenarlar: yansıtma
    out = np.zeros_like(f)
    for dy in range(3):
        for dx in range(3):                       # 9 kaydırılmış kopyanın ağırlıklı toplamı
            out += k[dy, dx] * p[dy: dy + f.shape[0], dx: dx + f.shape[1]]
    return out

mine = conv3(gray, k)
ref = cv2.filter2D(gray, -1, k, borderType=cv2.BORDER_REFLECT_101)
print('en büyük fark:', float(np.abs(mine[1:-1, 1:-1] - ref[1:-1, 1:-1]).max()))
cv2.imwrite('cikti.png', np.clip(ref, 0, 255).astype(np.uint8))   # float sonucu uint8 aralığına kırp
Python: gürültü ekle, dört filtreyi karşılaştır
import cv2
import numpy as np

img = cv2.imread('girdi.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
rng = np.random.default_rng(0)
noisy = gray.copy()
m = rng.random(gray.shape)
noisy[m < 0.03] = 0                               # %3 biber
noisy[m > 0.97] = 255                             # %3 tuz

out = {
    'box': cv2.blur(noisy, (5, 5)),
    'gauss': cv2.GaussianBlur(noisy, (5, 5), 1.2),
    'median': cv2.medianBlur(noisy, 5),           # tuz-biberde açık ara en iyisi
    'sharp': cv2.filter2D(noisy, -1, np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]])),
}
for name, f in out.items():
    print(f'{name:6s} PSNR = {cv2.PSNR(gray, f):5.1f} dB')   # yüksek PSNR: aslına daha yakın
cv2.imwrite('cikti.png', np.hstack([noisy, out['gauss'], out['median']]))

Sık yapılan hatalar

  • Çekirdek ağırlıklarını normalleştirmemek: toplamı 9 olan bir kutu filtresi görüntüyü dokuz kat parlatır ve doyurur.
  • Keskinleştirme sonucunu uint8'de hesaplamak: negatif değerler kaybolur; önce float, sonra kırp.
  • Tuz-biber gürültüsünü Gauss ile temizlemeye çalışmak: noktalar yalnız yayılır, medyan gerekir.
  • Büyük çekirdeği her karede çalıştırmak: 15×15 kutu filtresi integral görüntüyle ya da ayrılabilir geçişlerle çok daha hızlıdır.

Yazılım mühendisliği bağlantısı

Evrişimin elle yazılmış hâli ile kütüphane hâlini karşılaştırmak (yukarıdaki kodda olduğu gibi) bir referans uygulama testidir: yavaş ama açık kod, hızlı ama karmaşık kodu doğrular.

  • Kenar piksellerini ayrı test et; hataların çoğu kenar koşulundadır.
  • Performans için önce ölç (cv2.getTickCount ya da time.perf_counter), sonra optimize et.

Kendini sına

  1. [1 2 1; 2 4 2; 1 2 1] / 16 çekirdeği, ortası 160, diğer sekiz komşusu 0 olan bir 3×3 bölgede merkezde ne verir?

  2. Tuz-biber gürültüsü için en uygun filtre hangisidir?

  3. Keskinleştirme çekirdeğinin ağırlıkları toplamı neden 1'dir?

  4. Gauss filtresinin iki 1B geçişle yapılabilmesinin adı nedir?

Esc
  • PanelAna sayfaSayfa
  • ModüllerTüm modüllerSayfa
  • ParçalarParça ansiklopedisiSayfa
  • Mühendislik yoluBüyükler için robotik: 128 parça, 7 seviyeSayfa
  • Robotik dersi (ESOF 323)Üniversite robotik dersi, 14 haftaSayfa
  • Drone dersiBüyükler için: parça, simülasyon, yazılım; 10 üniteSayfa
  • Blok atölyesiSerbest blok programlamaAraç
  • Devre laboratuvarıSanal Arduino ve devreAraç
  • Robot arenasıSanal robot sürüşüAraç
  • OyunlarBloklarla 8 öğretici oyunAraç
  • Mikro Kart atölyesiSanal LED kartı bloklarla programlaAraç
  • Robot atölyesiMikro Kart'ı robota tak, bloklarla görev yapAraç