Ana içeriğe geç

Giriş8 dkB — Görüntü ve CNN

Görüntü verisi nedir

Önkoşul:Layer normalization

Kanca

1-24. derste hep vektörlerle (tek boyutlu sayı dizileri) çalıştık. Şimdi yeni bir bölüme başlıyoruz: Görüntü ve CNN. İlk adım basit ama temel: bir bilgisayar için bir “görüntü” aslında NEDİR?

Sezgi

Bir görüntü, bir sayı IZGARASIDIR. Her piksel, o noktadaki parlaklığı (gri tonlamalı) veya rengi (kırmızı/yeşil/mavi) temsil eden sayısal bir değer taşır. “Görüntü işleme”, aslında bu sayı ızgarası üzerinde matematik yapmaktır — ne kadar “görsel” görünse de, altında sadece bir tensör var.

Mekanizma

4×4’lük minik bir “görüntüyle” başlayalım:

Gri tonlamalı görüntü = sayı ızgarası

# Bir görüntü, aslında bir sayı IZGARASIDIR. Her piksel, 0 (siyah) ile 255 (beyaz)
# arasında TEK bir parlaklık değeri taşır (gri tonlamalı görüntülerde).
gri_resim = np.array([
    [0, 50, 100, 150],
    [50, 100, 150, 200],
    [100, 150, 200, 250],
    [150, 200, 250, 255],
], dtype=np.uint8)

print("Gri tonlamalı 'görüntü' şekli:", gri_resim.shape, "(yükseklik, genişlik)")
print(gri_resim)
print(f"\nSol üst piksel: {gri_resim[0,0]} (koyu/siyaha yakın)")
print(f"Sağ alt piksel: {gri_resim[3,3]} (açık/beyaza yakın)")
Gri tonlamalı 'görüntü' şekli: (4, 4) (yükseklik, genişlik)
[[  0  50 100 150]
 [ 50 100 150 200]
 [100 150 200 250]
 [150 200 250 255]]

Sol üst piksel: 0 (koyu/siyaha yakın)
Sağ alt piksel: 255 (açık/beyaza yakın)

Bu “görüntü”, aslında sadece 16 sayıdan oluşan bir 4×4 matris. Şimdi renkli (RGB) versiyona bakalım:

RGB: aynı ızgaranın 3 kopyası

# Renkli (RGB) bir görüntü, AYNI ızgaranın ÜÇ KOPYASIDIR -- kırmızı, yeşil, mavi
# kanalları. Her piksel artık TEK sayı değil, ÜÇ sayıdan oluşan bir vektör.
rgb_resim = np.zeros((4, 4, 3), dtype=np.uint8)
rgb_resim[:, :, 0] = gri_resim          # kırmızı kanal
rgb_resim[:, :, 1] = 255 - gri_resim    # yeşil kanal (tersine çevrilmiş)
rgb_resim[:, :, 2] = 128                # mavi kanal (sabit)

print(f"\nRGB görüntü şekli: {rgb_resim.shape} (yükseklik, genişlik, KANAL)")
print(f"Sol üst pikselin RGB değeri: {rgb_resim[0,0]} -- [kırmızı, yeşil, mavi]")
print(f"Sağ alt pikselin RGB değeri: {rgb_resim[3,3]}")
print("\nGri tonlamalı: (Y, G) şekli -- 1 kanal. RGB: (Y, G, 3) şekli -- 3 kanal.")

RGB görüntü şekli: (4, 4, 3) (yükseklik, genişlik, KANAL)
Sol üst pikselin RGB değeri: [  0 255 128] -- [kırmızı, yeşil, mavi]
Sağ alt pikselin RGB değeri: [255   0 128]

Gri tonlamalı: (Y, G) şekli -- 1 kanal. RGB: (Y, G, 3) şekli -- 3 kanal.

Çoğu kişi “renkli görüntü, gri tonlamalıdan çok daha karmaşık bir şey” sanır. Kısmen doğru, çünkü RGB aslında AYNI 4×4 ızgaranın SADECE 3 kopyası — her piksel artık tek bir sayı değil, [kırmızı, yeşil, mavi] şeklinde 3 sayılık bir liste.

Matematik

Görüntü tensörünün boyutları
Gri tonlama: (H,W)\text{Gri tonlama: } (H, W)RGB: (H,W,C)  veya  (C,H,W)\text{RGB: } (H, W, C) \; \text{veya} \; (C, H, W)
SembolAnlamı
HHYükseklik — piksel satırı sayısı
WWGenişlik — piksel sütunu sayısı
CCKanal sayısı — gri tonlamada 1, RGB’de 3

(H,W,C)(H, W, C) sırası “channels-last” (NumPy/Pillow gibi kütüphanelerin varsayılanı); (C,H,W)(C, H, W) sırası “channels-first” (PyTorch’un varsayılanı).

Kod

Normalizasyon ve format farkını görelim:

Normalizasyon ve channels-first/last

# Ham piksel değerleri (0-255) genelde [0,1] aralığına normalize edilir --
# 20. derste gördüğümüz gibi, büyük girdi değerleri eğitimi zorlaştırabilir.
normalize_resim = gri_resim.astype(np.float32) / 255.0
print(f"\nHam piksel aralığı: [{gri_resim.min()}, {gri_resim.max()}]")
print(f"Normalize edilmiş aralık: [{normalize_resim.min():.2f}, {normalize_resim.max():.2f}]")

# PyTorch, kanalları farklı bir SIRADA bekler: (kanal, yükseklik, genişlik) -- "channels-first"
tensor_chw = torch.from_numpy(rgb_resim).permute(2, 0, 1)
print(f"\nNumPy/görüntü kütüphaneleri format: {rgb_resim.shape} -- (Y, G, Kanal) 'channels-last'")
print(f"PyTorch format: {tuple(tensor_chw.shape)} -- (Kanal, Y, G) 'channels-first'")
print("Bu fark, PyTorch koduna yanlış şekilli bir tensör verildiğinde en sık karşılaşılan hatalardan biridir.")

Ham piksel aralığı: [0, 255]
Normalize edilmiş aralık: [0.00, 1.00]

NumPy/görüntü kütüphaneleri format: (4, 4, 3) -- (Y, G, Kanal) 'channels-last'
PyTorch format: (3, 4, 4) -- (Kanal, Y, G) 'channels-first'
Bu fark, PyTorch koduna yanlış şekilli bir tensör verildiğinde en sık karşılaşılan hatalardan biridir.
Soldan sağa: gri tonlamalı görüntü, kırmızı kanal, yeşil kanal, ve üç kanalın birleşimiyle oluşan RGB görüntü.
RGB bir görüntü, aynı ızgaranın üç renk kanalının BİRLEŞİMİDİR -- her kanal kendi başına gri tonlamalı bir görüntü gibi düşünülebilir.

Nerede işe yarar

Bu format farkları, pratikte en sık karşılaşılan hataların kaynağıdır:

  • PyTorch modellerine görüntü verirken (C, H, W) sırası beklenir — Pillow/OpenCV gibi kütüphaneler genelde (H, W, C) üretir, dönüşüm (.permute() veya torchvision.transforms) gerekir.
  • Piksel değerleri neredeyse HER ZAMAN [0,1] veya standartlaştırılmış (mean/std) aralığa normalize edilir — 20. dersteki ilklendirme hassasiyeti, ham [0,255] girdilerle eğitimi zorlaştırır.
  • Gri tonlamalı görüntüler bile genelde (1, H, W) şeklinde tutulur — kanal boyutu, sadece 1 olsa bile GENELDE atılmaz.

Bu 3 hatayı yaparsın:

  1. (H, W, C) formatındaki bir görüntüyü, dönüştürmeden PyTorch’a vermek — boyut uyuşmazlığı hatası (veya daha kötüsü, sessiz bir yanlış yorumlama) alırsın.
  2. Piksel değerlerini [0,255] aralığında bırakıp normalize etmeyi unutmak.
  3. Kanal sayısını görmezden gelip gri tonlamalı ve RGB görüntüleri aynı şekilde işlemeye çalışmak.

Kendini test et

1. RGB bir görüntü, gri tonlamalı bir görüntüden temelde nasıl farklıdır?
  1. RGB tamamen farklı bir veri türüdür, sayılarla ifade edilemez
  2. RGB, AYNI piksel ızgarasının kırmızı/yeşil/mavi olmak üzere 3 kopyasıdır -- her piksel artık 1 değil 3 sayı taşır (doğru cevap)
  3. RGB sadece görsel bir efekttir, veri olarak önemi yoktur
  4. Gri tonlamalı görüntüler RGB'den daha fazla veri içerir

Neden: RGB bir görüntü, aynı (H, W) ızgarasının 3 renk kanalının (kırmızı, yeşil, mavi) bir arada tutulmasıdır -- her piksel artık [kırmızı, yeşil, mavi] şeklinde 3 sayılık bir vektördür.

2. PyTorch'un 'channels-first' formatı ((C, H, W)) ne anlama gelir?
  1. Görüntünün sadece 1 kanalı olduğu anlamına gelir
  2. Tensörün boyut sırasının önce KANAL, sonra yükseklik, sonra genişlik olduğu anlamına gelir -- NumPy/Pillow'un (H, W, C) sırasından farklıdır (doğru cevap)
  3. Kanalların önemsiz olduğu anlamına gelir
  4. Sadece gri tonlamalı görüntüler için geçerlidir

Neden: PyTorch tensörleri (C, H, W) sırasını bekler; bu, NumPy/Pillow gibi kütüphanelerin varsayılan (H, W, C) sırasından farklıdır -- bu yüzden dönüşüm (permute) gerekir.

3. Piksel değerlerini [0,255] yerine [0,1] aralığına normalize etmenin nedeni nedir?
  1. Görüntüyü küçültmek için
  2. 20. derste gördüğümüz gibi, büyük ölçekli girdi değerleri eğitimi zorlaştırabilir -- normalize edilmiş girdiler, ağırlık ilklendirme varsayımlarıyla daha uyumludur (doğru cevap)
  3. Sadece dosya boyutunu küçültmek için
  4. PyTorch [0,255] değerlerini kabul etmez

Neden: 20. dersteki ağırlık ilklendirme tartışmasını hatırla: ağırlıklar belirli bir girdi ölçeği varsayımıyla ilklendirilir; ham [0,255] gibi büyük, standartlaştırılmamış girdiler bu varsayımı bozup eğitimi zorlaştırabilir.

Özet

Özet

  • Bir görüntü, bilgisayar için bir sayı ızgarasıdır (tensördür) -- "görsel" olması bu gerçeği değiştirmez.
  • Gri tonlamalı görüntüler (H, W) şeklinde, RGB görüntüler (H, W, C) veya (C, H, W) şeklindedir.
  • PyTorch "channels-first" ((C, H, W)) formatı bekler; NumPy/Pillow genelde "channels-last" ((H, W, C)) üretir.
  • Piksel değerleri genelde [0,255]'ten [0,1]'e (veya standartlaştırılmış bir aralığa) normalize edilir.
  • Bu format farkları, pratikte en sık karşılaşılan boyut/şekil hatalarının kaynağıdır.
Sonraki adım: Neden tam bağlı ağ yetmez →