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ı
| Sembol | Anlamı |
|---|---|
| Yükseklik — piksel satırı sayısı | |
| Genişlik — piksel sütunu sayısı | |
| Kanal sayısı — gri tonlamada 1, RGB’de 3 |
sırası “channels-last” (NumPy/Pillow gibi kütüphanelerin varsayılanı); 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.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()veyatorchvision.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:
(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.- Piksel değerlerini [0,255] aralığında bırakıp normalize etmeyi unutmak.
- 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?
- RGB tamamen farklı bir veri türüdür, sayılarla ifade edilemez
- 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)
- RGB sadece görsel bir efekttir, veri olarak önemi yoktur
- 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?
- Görüntünün sadece 1 kanalı olduğu anlamına gelir
- 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)
- Kanalların önemsiz olduğu anlamına gelir
- 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?
- Görüntüyü küçültmek için
- 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)
- Sadece dosya boyutunu küçültmek için
- 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.