Bilgisayarlı Görüye Giriş - Görüntünün Temelleri
2026
Bu dersin sonunda:
4xdu3hzxclassroom.google.com → Sınıfa katıl → kodu girin (kurumsal hesapla).
Gerçek dünya analog bir sinyaldir. Dijital görüntü elde etmek iki temel adımdan geçer:
Örnekleme (Sampling): Uzamsal olarak sürekli olan görüntüden ayrık konumlarda değer alma işlemidir. Aynı görüntü alanında daha sık örnekleme, daha fazla piksel üretir.
Kuantalama (Quantization): Her örneğin yoğunluk değerini sonlu sayıdaki seviyelerden birine atama işlemidir. Kullanılan bit derinliği, kaç farklı seviyenin temsil edilebileceğini belirler.
Not
Bulanık bir görüntüyü 1920 × 1080’den 3840 × 2160’a büyütmek piksel sayısını artırır; çekim sırasında kaybolan gerçek ayrıntıları geri getirmez.
Gri seviye bir görüntüde piksel başına \(b\) bit, \(L = 2^b\) farklı seviye temsil eder.
| Bit derinliği | Seviye sayısı | Görsel etki |
|---|---|---|
| 1-bit | 2 | Yalnızca siyah ve beyaz |
| 2-bit | 4 | Belirgin ton basamakları |
| 4-bit | 16 | Daha ince ton geçişleri |
| 8-bit | 256 | Daha yumuşak ton geçişleri |
Tüm şeritlerde 256 örnek konumu var. Değişen, her konuma atanabilecek gri seviye sayısı.
Örnekleme: Nereden ve ne sıklıkla değer alıyoruz? Kuantalama: Bu değeri hangi seviyeye atıyoruz?
Aliasing: Örnekleme frekansı, sinyaldeki en yüksek frekansı yakalamak için yeterli değilse (Nyquist Teoremi), yüksek frekanslı desenler daha düşük frekanslı yapılar gibi “kılık değiştirir”. Bu, görüntülerde moiré desenleri veya pürüzlü kenarlar olarak ortaya çıkar.
Uyarı
Aliasing’den Kaçınmak İçin Sezgisel Kural: Bir görüntüyü küçültmek (downsampling), örnekleme oranını düşürmek demektir. Küçültme öncesi görüntüye düşük geçiren bir filtre (örn: hafif bir bulanıklaştırma/blur) uygulamak, aliasing artefaktlarını önemli ölçüde azaltır.
Bulanıklaştırma: Yüksek frekanslı (ince çizgili) bir desenin, küçültüldüğünde oluşan rahatsız edici moiré desenleri (aliasing) ve öncesinde blur uygulanarak küçültülmüş daha temiz versiyonu.
Sinyalin bant sınırlı olduğunu, yani \(f_{max}\) üzerinde frekans bileşeni içermediğini varsayalım. İdeal örnekleme ve yeniden oluşturma koşullarında, sinyalin kayıpsız yeniden oluşturulabilmesi için yeterli koşul:
\[ f_s > 2 \, f_{max} \]
Burada:
\(f_s\) örnekleme frekansı (örnek sayısı/saniye)
\(f_{max}\) sinyaldeki en yüksek frekans bileşeni
Başka bir deyişle: En yüksek frekanslı bileşenin her periyodunda ikiden fazla örnek almalısın. Bu koşul, kuantalama veya ölçüm gürültüsünden doğan kayıpları ortadan kaldırmaz.
Bant sınırlı bir ses sinyalinin en yüksek frekansı 10 kHz ise:
\[ f_{max} = 10{,}000 \text{ Hz} \]
Nyquist’e göre:
\[ f_s > 2 \times 10{,}000 = 20{,}000 \text{ Hz} \]
CD kalitesinde ses 44.1 kHz ile örneklenir,
çünkü insan kulağı yaklaşık 20 kHz’e kadar duyabilir.
Görüntülerde frekans, pikseller arasındaki değişim hızını temsil eder.
Not
Çözüm: Küçültme (downsampling) işlemi öncesinde düşük geçiren bir filtre (blur) uygulayarak yüksek frekansları bastırmak, aliasing etkisini önemli ölçüde azaltır.
| Durum | Örnekleme Oranı | Görsel / Sonuç |
|---|---|---|
| \(f_s < 2f_{max}\) | Yetersiz örnekleme | Aliasing riski; kayıpsız yeniden oluşturma garantisi yok |
| \(f_s = 2f_{max}\) | Nyquist sınırı | Sınır frekansındaki bileşen örnekleme fazına bağlı olarak kaybolabilir |
| \(f_s > 2f_{max}\) | Yeterli örnekleme | Bant sınırlı sinyal, ideal koşullarda yeniden oluşturulabilir |
Not
Tam sınırda, sinüs dalgasının yalnızca sıfır geçişlerini örnekleyebiliriz: dalga var olduğu hâlde tüm örnekler sıfır olur. Yeterli örnekleme oranının üzerine çıkmak daha fazla veri üretir; tek başına daha doğru bir ölçüm garantilemez.
Piksel: Bir dijital görüntünün en küçük temel yapı taşıdır. Genellikle tek bir sayısal değer (gri seviye) veya bir dizi değer (renkli) ile temsil edilir.
Koordinat Sistemi:
img[row, col] veya img[y, x] kullanımına dikkat etmek kritiktir.Koordinat Sistemi
\[ img = \begin{pmatrix} 10 & 11 & 12 & 13 \\ 20 & 21 & 22 & 23 \\ 30 & 31 & 32 & 33 \end{pmatrix} \]
Amaç: \((x=1,\,y=2)\) pikselini okumak
img[y, x] = img[2, 1] = 31img[x, y] = img[1, 2] = 22[0, 255] aralığında bir değer alır (0=Siyah, 255=Beyaz).(Yükseklik, Genişlik)(R, G, B) şeklinde bir demet.(Yükseklik, Genişlik, 3)Önemli
OpenCV, görüntüleri varsayılan olarak BGR (Blue, Green, Red) formatında okur!
Gri seviyeye dönüşüm, genellikle üç kanalın basit aritmetik ortalaması değildir. OpenCV’nin RGB/BGR → gri seviye dönüşümünde kanallar farklı ağırlıklarla birleştirilir:
\[ Y = 0.299R + 0.587G + 0.114B \]
Önemli
Üç kanal tek bir değere indirgenirken renk bilgisi kaybolur. Farklı renkler aynı gri seviyeye dönüşebilir; gri görüntüden özgün renkler geri elde edilemez.
Görüntüler matrislerdir, ancak bu matrislerin elemanlarının veri tipi (dtype) önemlidir.
uint8 (Unsigned 8-bit Integer): En yaygın format. [0, 255] aralığındaki tam sayıları saklar. Bellek verimlidir.float32 (32-bit Floating Point): Genellikle [0.0, 1.0] aralığına normalize edilmiş değerler için kullanılır. Derin öğrenme modelleri ve bazı hassas hesaplamalar için gereklidir.Kırpma (Clipping): uint8 bir görüntüye yapılan işlemler (örn: parlaklık artırma) sonucu değerler [0, 255] aralığının dışına çıkabilir. Bu değerlerin bu aralığa zorlanmasına “clipping” denir. np.clip() bu iş için idealdir.
Not
Gamma Düzeltmesi (Gamma Correction): İnsan gözü parlaklığı lineer olarak algılamaz. Monitörler bunu telafi etmek için görüntüleri “gamma-kodlu” olarak saklar. İşlemlerin fiziksel olarak doğru olması için bazen bu gamma’yı tersine çevirip “lineer” uzayda çalışmak gerekebilir.
Her bir piksele bağımsız olarak uygulanırlar.
Formülasyon: \(I_{out}(x, y) = \text{clip}(\alpha \cdot I_{in}(x, y) + \beta, 0, 255)\)
Bu işlemler, görüntü histogramını sağa/sola kaydırır (\(\beta\)) veya genişletir/daraltır (\(\alpha\)).
Görüntüleri yeniden boyutlandırma, döndürme gibi işlemler piksellerin yerini değiştirir. Bu sırada yeni piksel değerlerinin hesaplanması gerekir.
| Kavram | İlke / Not | OpenCV Fonksiyonları |
|---|---|---|
| İnterpolasyon | Piksel değerlerini tahmin etme yöntemi. NEAREST (hızlı, pürüzlü), LINEAR (dengeli), CUBIC (yavaş, pürüzsüz) arasında hız-kalite dengesi vardır. | cv2.resize, cv2.warpAffine |
| Sınır Yönetimi | Görüntü kenarlarının dışındaki pikseller için varsayılan davranış. CONSTANT (sabit renk), REPLICATE (kenar pikselini tekrarla), REFLECT (yansıt) gibi modlar vardır. | borderMode= argümanı |
Bir görüntüyü yeniden boyutlandırdığımızda hedef piksel konumlarını kaynak görüntünün piksel ızgarasına eşleriz. Bu konumlar kaynak piksel merkezleriyle her zaman çakışmaz.
İnterpolasyon, hedef piksel değerlerini kaynak görüntüdeki komşu piksel değerlerinden hesaplama yöntemidir.
Seçilen algoritma; hız, kalite ve sonuçtaki pürüzsüzlük/keskinlik arasında bir denge kurar.
Büyütmede daha fazla piksel üretiriz; bu piksellerin değerlerini hangi kuralla hesaplayacağımıza karar vermemiz gerekir.
\[ \begin{pmatrix} 120 & 121 & 115 \\ 100 & 110 & 90 \\ 100 & 80 & 60 \end{pmatrix} \]
Gösterimi sadeleştirmek için yukarıdaki görüntünün sol üst 2×2 bölgesini kullanalım. Artık hedefimiz 9×9 değil, 6×6 boyutlu bir görüntü.
Not
Aşağıdaki konum taşıma ve sıfır doldurma adımları, yeni piksel değerlerine neden ihtiyaç duyduğumuzu göstermek içindir. cv2.resize bu boşlukları oluşturup sıfırla dolduran bir süreç uygulamaz; hedef piksel değerlerini seçilen yöntemle hesaplar.
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & & & 121 & & \\ & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ & & & & & \\ \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & & & 121 & & \\ & & & & & \\ & & & & & \\ 100 & & & & & \\ & & & & & \\ & & & & & \\ \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & & & 121 & & \\ & & & & & \\ & & & & & \\ 100 & & & 110 & & \\ & & & & & \\ & & & & & \\ \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 0 & 0 & 121 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ 100 & 0 & 0 & 110 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ 0 & 0 & 0 & 0 & 0 & 0 \\ \end{pmatrix} \]
INTER_NEAREST (En Yakın Komşu)INTER_LINEAR (Bilinear)INTER_CUBIC (Bicubic)INTER_AREAINTER_LANCZOS4INTER_NEAREST (En Yakın Komşu)Diyelim ki:
En Yakın Komşu İnterpolasyonu
Hedef piksel \((x_t, y_t)\) için, OpenCV INTER_NEAREST yöntemindeki eşleme kuralını kullanalım:
\[ x_s = \left\lfloor \frac{x_t W_s}{W_t} \right\rfloor , \quad y_s = \left\lfloor \frac{y_t H_s}{H_t} \right\rfloor \]
Burada:
En Yakın Komşu İnterpolasyonu
Boyut: (2 x 2)
Ölçekleme faktörü: (3)
Yeni boyut: (6 x 6)
Her hedef piksel \((x_t, y_t)\) için kaynak koordinatlar:
\[ x_s = \left\lfloor \frac{x_t \cdot 2}{6} \right\rfloor = \left\lfloor \frac{x_t}{3} \right\rfloor \\ y_s = \left\lfloor \frac{y_t \cdot 2}{6} \right\rfloor = \left\lfloor \frac{y_t}{3} \right\rfloor \]
En Yakın Komşu İnterpolasyonu
| Hedef Satır (\(y_t\)) | Kaynak Satır (\(y_s\)) |
|---|---|
| 0, 1, 2 | 0 |
| 3, 4, 5 | 1 |
| Hedef Sütun (\(x_t\)) | Kaynak Sütun (\(x_s\)) |
|---|---|
| 0, 1, 2 | 0 |
| 3, 4, 5 | 1 |
En Yakın Komşu İnterpolasyonu
Her bölge için kaynak indeksler \([y_s, x_s]\) (satır, sütun) sırasındadır:
[0, 0] → 120[0, 1] → 121[1, 0] → 100[1, 1] → 110En Yakın Komşu İnterpolasyonu
\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
\[ \begin{pmatrix} 120 & 120 & 120 & 121 & 121 & 121 \\ 120 & 120 & 120 & 121 & 121 & 121 \\ 120 & 120 & 120 & 121 & 121 & 121 \\ 100 & 100 & 100 & 110 & 110 & 110 \\ 100 & 100 & 100 & 110 & 110 & 110 \\ 100 & 100 & 100 & 110 & 110 & 110 \end{pmatrix} \]
INTER_LINEAR (Bilinear)Koordinat Sistemi
Yeni hedef piksel (x, y), kaynak görüntüde tam sayı olmayan bir noktaya denk gelebilir:
\[ x = i + a, \quad y = j + b \quad \text{(0 ≤ a, b < 1)} \]
Buradaki (i, j), bulunduğu hücrenin sol üst köşe koordinatıdır.
Formül
\[ I(x, y) = (1 - a)(1 - b) \cdot Q_{00} + a(1 - b) \cdot Q_{10} + (1 - a)b \cdot Q_{01} + ab \cdot Q_{11} \]
Köşeler:
\[\begin{aligned} Q_{00} &= I(i,j) && \text{(sol-üst)} \\ Q_{10} &= I(i, j+1) && \text{(sağ-üst)} \\ Q_{01} &= I(i+1, j) && \text{(sol-alt)} \\ Q_{11} &= I(i+1, j+1) && \text{(sağ-alt)} \end{aligned}\]\[ \begin{pmatrix} 120 & 121 \\ 100 & 110 \end{pmatrix} \]
Boyut: (2 x 2)
Hedef boyut: (6 x 6)
Ölçek faktörü: (3 )
Koordinat Dönüşümü
Her hedef piksel ((i, j)) için:
\[ x = \frac{i}{3}, \quad y = \frac{j}{3} \]
(x, y) koordinatı hangi kaynak hücreye düştüyse, o hücredeki 4 komşu piksel ile interpolasyon uygulanır.
Örnek Hesaplama – Piksel (1, 1)
\[ x = \frac{1}{3}, \quad y = \frac{1}{3} \Rightarrow a = 0.33, \quad b = 0.33 \]
4 komşu değer:
\[\begin{aligned} Q_{00} &= 120 \\ Q_{10} &= 100 \\ Q_{01} &= 121 \\ Q_{11} &= 110 \end{aligned}\]Formüle göre: \[ \begin{aligned} I(0,0) &= (1 - 0.33)(1 - 0.33) \cdot 120 + 0.33(1 - 0.33) \cdot 100 \\\\ &\quad + (1 - 0.33)(0.33) \cdot 121 + 0.33 \cdot 0.33 \cdot 110 \\\\ &= 0.4489 \cdot 120 + 0.2211 \cdot 100 + 0.2211 \cdot 121 + 0.1089 \cdot 110 \\\\ &\approx 53.9 + 22.1 + 26.8 + 12.0 = \boxed{114.8} \end{aligned} \]
Diğer Örnek – Piksel (3, 3)
\[ x = \frac{3}{3} = 1, \quad y = \frac{3}{3} = 1 \Rightarrow a = 0, b = 0 \]
Doğrudan \[ Q_{22} = 110 \] ’a düşer:
\[ I(3, 3) = 110 \]
Sonuç: Yaklaşık 6x6 Matris (Doğrusal İnterpolasyon ile)
\[ \begin{pmatrix} 120 & 120.3 & 120.6 & 121 & 121 & 121 \\\\ 116.6 & 116.2 & 115.8 & 117.3 & 117.0 & 116.6 \\\\ 113.2 & 112.2 & 111.2 & 113.6 & 112.9 & 112.2 \\\\ 100 & 100.3 & 100.6 & 110 & 110 & 110 \\\\ 100 & 100.3 & 100.6 & 110 & 110 & 110 \\\\ 100 & 100.3 & 100.6 & 110 & 110 & 110 \end{pmatrix} \]
INTER_LINEAR (Bilinear):
cv2.resize fonksiyonunun varsayılan yöntemidir.INTER_CUBIC (Bicubic)INTER_LINEAR’dan daha pürüzsüz ve daha kaliteli sonuçlar üretir. Biraz daha yavaştır.INTER_AREAINTER_LANCZOS4Farklı yöntemlerin sonuçları, özellikle aşırı büyütme veya küçültme işlemlerinde belirginleşir.
Gri seviye bir görüntüdeki histogram, her bir parlaklık seviyesindeki piksel sayısını sayar:
\[ h(r_k) = \text{Görüntüde } r_k \text{ değerine sahip piksel sayısı} \]
Bu değer, toplam piksel sayısına bölünerek bir olasılık dağılımı olarak da ifade edilebilir (normalize edilmiş histogram).
Histogram, bir görüntüyü nicel olarak anlamamızı sağlar:
| Histogram Görünümü | Görsel Yorumlama |
|---|---|
| Piksel dağılımı solda yoğunlaşmışsa | Görüntü genel olarak karanlık tonlara sahiptir. |
| Piksel dağılımı sağda yoğunlaşmışsa | Görüntü genel olarak çok parlak veya “yanmış”tır. |
| Dağılım dar bir aralıkta sıkışmışsa | Görüntü düşük kontrastlıdır, “soluk” görünür. |
| Dağılım tüm eksene yayılmışsa | Görüntü dengeli ve iyi bir kontrasta sahiptir. |
Basit bir eşik değeri \(T\) seçilir. Görüntüdeki her piksel bu değerle karşılaştırılır:
\[ I_{hedef}(x, y) = \begin{cases} 0 \text{ (siyah)}, & I_{kaynak}(x, y) < T \\ 255 \text{ (beyaz)}, & I_{kaynak}(x, y) \geq T \end{cases} \]
Bu işlemin sonucunda ikili (binary) bir görüntü elde edilir.
Histogramda birbirinden belirgin şekilde ayrılmış iki tepe (mod) varsa, bu iki grup büyük olasılıkla nesneye ve arka plana aittir.
Bu iki tepenin arasındaki vadi, eşik değeri \(T\) için ideal bir adaydır.
Her görüntü için bu eşiği elle seçmek pratik değildir. Bu nedenle otomatik bir yönteme ihtiyaç duyarız.
Öncelikle, her bir gri seviyenin (\(k\)) görüntüde bulunma olasılığı (\(p_k\)) hesaplanır:
\[ p_k = \frac{\text{Görüntüdeki } k \text{ değerli piksel sayısı}}{\text{Toplam piksel sayısı}} \]
Bu, normalize edilmiş histogramdır.
Her bir olası eşik değeri \(T\) için, pikseller iki sınıfa ayrılır:
Bu sınıfların olasılıkları (\(\omega\)) ve ortalama parlaklık değerleri (\(\mu\)) hesaplanır.
Otsu’nun maksimize etmeye çalıştığı değer, iki sınıf arasındaki varyanstır (\(\sigma_b^2\)):
\[ \sigma_b^2(T) = \omega_0(T) \cdot \omega_1(T) \cdot \left[ \mu_0(T) - \mu_1(T) \right]^2 \]
Bu değer, iki sınıfın ne kadar iyi ayrıldığının bir ölçüsüdür.
Algoritma, tüm olası \(T\) değerleri (1’den 254’e kadar) için sınıflar arası varyansı hesaplar.
Varyansı maksimize eden \(T\) değeri, optimal eşik olarak seçilir:
\[ T_{optimal} = \arg\max_T \sigma_b^2(T) \]
Histogram eşitleme, bir görüntünün kümülatif dağılım fonksiyonunu (CDF) kullanarak her bir pikselin değerini yeniden haritalar.
Temel prensip, yoğun olan piksel aralıklarını genişletmek ve seyrek olan aralıkları daraltmaktır.
\[ I_{yeni}(x,y) = \text{round} \left( (L - 1) \cdot \text{CDF}(I_{eski}(x,y)) \right) \]
OpenCV ile görüntü okumak ve temel özelliklerine erişmek oldukça basittir.
import cv2
import numpy as np
import matplotlib.pyplot as plt
# Görüntüyü renkli ve gri seviye olarak oku
img_color = cv2.imread('/assets/images/courses/bilgisayarli-goru/lecture1/sample.jpg', cv2.IMREAD_COLOR)
img_gray = cv2.imread('/assets/images/courses/bilgisayarli-goru/lecture1/sample.jpg', cv2.IMREAD_GRAYSCALE)
# Boyutlar (yükseklik, genişlik, kanal)
height, width, channels = img_color.shape
print(f"Renkli Görüntü: {height}x{width}, {channels} kanal, Veri Tipi: {img_color.dtype}")
# Gri seviye görüntünün kanal bilgisi yoktur
h_gray, w_gray = img_gray.shape
print(f"Gri Seviye Görüntü: {h_gray}x{w_gray}, Veri Tipi: {img_gray.dtype}")Görüntüler NumPy dizisi olduğu için standart indeksleme kuralları geçerlidir.
# (y, x) = (satır, sütun) koordinatları
y, x = 100, 50
# Belirtilen koordinattaki pikselin BGR değerini al
px_val = img_color[y, x]
print(f"Piksel ({y}, {x}) BGR değeri: {px_val}")
# Sadece Mavi (Blue) kanalının değerini al (B=0, G=1, R=2)
blue_val = img_color[y, x, 0]
print(f"Piksel ({y}, {x}) Mavi değeri: {blue_val}")
# Bir bölgeyi (Region of Interest - ROI) kesip al
# .copy() kullanmak, ROI'deki değişikliklerin orijinal görüntüyü etkilemesini önler
roi = img_color[100:200, 200:300].copy()
# Orijinal görüntüde bir pikseli siyaha boyayalım
img_color[100, 200] = (0, 0, 0) Matplotlib gibi kütüphaneler RGB formatını beklerken, OpenCV BGR kullanır. Doğru görselleştirme için dönüşüm şarttır.
Histogram, bir görüntüdeki piksel yoğunluk dağılımını göstererek bize parlaklık ve kontrast hakkında hızlı bilgi verir.
# Gri seviye histogram (matplotlib ile)
plt.figure(figsize=(8,5))
plt.hist(img_gray.ravel(), bins=256, range=(0,256))
plt.title('Gri Seviye Histogram'); plt.xlabel('Yoğunluk'); plt.ylabel('Frekans')
plt.xlim(0,255); plt.grid(True); plt.show()
# R, G, B kanal histogramları (OpenCV + matplotlib)
colors = ('b','g','r')
plt.figure(figsize=(8,5)); plt.title('Kanal Bazlı Histogramlar')
for i, col in enumerate(colors):
hist = cv2.calcHist([img_color], [i], None, [256], [0,256])
plt.plot(hist, color=col)
plt.xlabel('Yoğunluk'); plt.ylabel('Frekans')
plt.xlim(0,256); plt.grid(True); plt.show()cv2.imread() ile okunan bir renkli görüntüde, img[0, 0, 0] hangi renk kanalını temsil eder?
Bilgisayarla Görü – OMÜ | 🏠