processed image (13)

Sinyalden Piksele: OpenCV ile Görüntü İşleme ve Temel Algoritmalar

Sinyalden Piksele: OpenCV ile Görüntü İşleme ve Temel Algoritmalar

1. Giriş: Bilgisayarlı Görü Dünyasında Görüntü İşlemenin Rolü

Yapay zeka ve bilgisayarlı görü (Computer Vision) alanında çalışan mühendisler olarak, karmaşık nesne tespiti (object detection), otonom sürüş algoritmaları veya derin öğrenme tabanlı segmentasyon modelleri geliştirmeden önce yüzleştiğimiz ilk gerçek şudur: Modelinizin başarısı, ona beslediğiniz verinin kalitesiyle doğrudan orantılıdır.

Bugün Yolo, ResNet veya Vision Transformer (ViT) gibi modern mimarileri birkaç satır kodla çağırmak oldukça kolay. Ancak gerçek dünyadan gelen ham görsel verisi; uyumsuz aydınlatmalar, kamera gürültüleri (noise), perspektif kaymaları ve gereksiz arka plan detaylarıyla doludur. İşte tam bu noktada, ham piksel verisini modele hazır hale getiren ve sinyal seviyesinde işleyen Sayısal Görüntü İşleme (Digital Image Processing) teknikleri devreye girer.

Görüntü Nedir? 2D/3D Matris Realitesi

İnsan gözü için bir fotoğraf bir nesne, bir yüz veya bir manzara anlamı taşır. Ancak bir bilgisayar ve temsil ettiği algoritmalar için durum tamamen farklıdır: Görsel dediğimiz şey, matrislerden ibaret sayı dizileridir.

Bir dijital görüntüyü matematikle ifade etmek istersek, bunu iki boyutlu bir süreksiz sinyal fonksiyonu f(x,y) olarak tanımlayabiliriz:

  • x ve y, görsel üzerindeki mekânsal (spatial) koordinatları ifade eder.
  • f(x,y) fonksiyonunun ürettiği genlik (amplitude) değeri ise o koordinattaki piksel yoğunluğunu (intensity) belirtir.
Görsel Tipi Özellikleri
Gri Tonlamalı (Grayscale) Tek bir kanala (1 matris katmanı) sahiptir. Her bir piksel 0 (tam siyah / yansıma yokluğu) ile 255 (tam beyaz / maksimum genlik) arasında değer alan 8-bitlik tamsayılardan (uint8) oluşur.
Renkli Görseller (RGB / BGR) Üç ayrı kanala (3 matris katmanı) sahiptir: Kırmızı (Red), Yeşil (Green) ve Mavi (Blue). Her bir kanal 0-255 arasında değer alır ve bu üç katmanın matris bileşimi renk yelpazesini oluşturur.

OpenCV ve Python Ekosistemi

Bilgisayarlı görü mimarisinde temel yapı taşı olan OpenCV, C++ tabanlı altyapısıyla yüksek performans sağlarken Python arayüzü ile de hızlı prototipleme imkanı sunar.

OpenCV'yi güçlü kılan en kritik unsur, görselleri doğrudan NumPy dizileri (ndarray) olarak içeri almasıdır. Bu durum; bir görsel üzerinde filtreleme yaparken veya renk kanallarını ayırırken standart C döngülerine muhtaç kalmadan, NumPy'ın matris gücünden yararlanmamızı sağlar.

Kritik Bir Detay: BGR vs. RGB Renk Uzayı Farkı

OpenCV ile çalışmaya başlayan mühendislerin karşılaştığı ilk klasik tuzak, renk formatı uyumsuzluğudur. Standart kütüphaneler (Matplotlib, PIL, PyTorch) renkleri RGB sırasıyla okurken, OpenCV tarihsel donanım sebepleriyle görselleri varsayılan olarak BGR (Blue - Green - Red) sırasıyla yükler. Eğer dönüşüm yapmazsanız insan yüzleri mavi görünecektir.

import cv2
import matplotlib.pyplot as plt

# Görseli BGR olarak belleğe yükle
image_bgr = cv2.imread("sample.jpg")

# OpenCV BGR -> Standart RGB dönüşümü
image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)

# Siyah-Beyaz (Grayscale) okuma işlemi
image_gray = cv2.imread("sample.jpg", cv2.IMREAD_GRAYSCALE)

2. Veri Akışı ve Temel Manipülasyonlar (I/O, Resizing & Drawing)

Görsel ve Video Akışlarının Belleğe Yüklenmesi (I/O)

Durağan görseller cv2.imread() ile okunurken, video akışları zaman boyutunda (t) ardışık olarak sıralanmış durağan kareler (frames) dizisidir. Kamera akışını yönetirken I/O katmanında defansif bir yaklaşım sergilemeliyiz:

import cv2

# Video akışını başlat (Dosya yolu veya 0: varsayılan kamera cihazı)
cap = cv2.VideoCapture("traffic_sample.mp4")

# Akışın başarıyla açılıp açılmadığını kontrol et (Defansif Kodlama)
if not cap.isOpened():
    raise IOError("Video kaynağı okunamadı!")

while cap.isOpened():
    # ret (bool): Kare başarılı okundu mu?, frame: Piksel matrisi
    ret, frame = cap.read()
    if not ret: break
        
    cv2.imshow("Video Stream Pipeline", frame)
    if cv2.waitKey(1) & 0xFF == ord('q'): break

cap.release()
cv2.destroyAllWindows()

Performans ve Bellek Yönetimi: Resizing & Crop (ROI)

Görsel verinin çözünürlüğü arttıkça piksel sayısı kareyle doğru orantılı olarak büyür. Derin öğrenme modellerine bu boyutta veri beslemek; yüksek bellek harcamasına ve çıkarım sürelerinin uzamasına neden olur.

Orijinal Görüntü (H x W)
İçindeki ROI Alanı
➡ Kırpma (Slicing) ➡
İlgilenilen Bölge (h x w)
[y1:y2, x1:x2]

OpenCV bir görüntüyü NumPy array olarak tuttuğu için kırpma işlemi ek bir fonksiyon çağrısı gerektirmez; doğrudan Array Slicing ile yapılır. NumPy matris indekslemesinde ilk eksen Y satırlarını (Yükseklik), ikinci eksen X sütunlarını (Genişlik) temsil eder.

# Y-ekseninde 100-300 px, X-ekseninde 200-400 px arası ROI kırpma
roi = image[100:300, 200:400]

# Piksel boyutunu 512x512 seviyesine çekme
resized_img = cv2.resize(image, (512, 512), interpolation=cv2.INTER_AREA)

Görsel Anotasyon ve FOURCC Codec Yapısı

Model tahminlerini, nesne tespiti sonuçlarını (Bounding Box) veya sınıflandırma skorlarını sunmak için görsel üzerine vektörel şekiller ve metinler eklenir. İşlenmiş akışı diske kaydetmek içinse cv2.VideoWriter ve FOURCC codec tanımlanır.

# Bounding Box Çizimi: Sol-üst(100,100), Sağ-alt(300,300), Mavi, 2px kalınlık
cv2.rectangle(frame, (100, 100), (300, 300), (255, 0, 0), 2)

# Sıkıştırma Formatı: XVID
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter('output.avi', fourcc, 20.0, (640, 480))

3. Geometrik ve Ağırlıklı Dönüşümler (Blending & Perspective)

Perspektif Düzeltme (Perspective Transformation)

Derin öğrenme modelleri nesneleri belirli bir açıdan gördüğünde eğitildiyse; yamuk, açılı veya perspektifi kaymış bir görselle karşılaştığında başarım oranı ciddi şekilde düşer. Algoritmik seviyede görselin kuş bakışı (top-down) hale getirilmesi gerekir.

Bunun için 3x3 boyutunda homojen bir Perspektif Dönüşüm Matrisi hesaplanır.

x'
y'
1
= M ·
x
y
1
=
m00m01m02
m10m11m12
m20m21m22
·
x
y
1
# 4 Kaynak (src) ve 4 Hedef (dst) noktası tanımlanır
matrix = cv2.getPerspectiveTransform(src_points, dst_points)
output = cv2.warpPerspective(image, matrix, (width, height))

Görüntü Karıştırma (Image Blending)

İki görüntüyü basitçe img1 + img2 şeklinde toplamak doğru sonuç vermez. Çünkü iki uint8 matris toplandığında 255 değerini aşan pikseller taşar (overflow). Düzgün bir harmanlama için ağırlıklı toplam formülü kullanılır:

I(x,y) = α · I1(x,y) + β · I2(x,y) + γ
# KRİTİK ADIM: Görsellerin boyutları BİREBİR EŞİT olmalıdır.
img1_resized = cv2.resize(img1, (600, 600))
img2_resized = cv2.resize(img2, (600, 600))

# Blending İşlemi: alpha=0.7, beta=0.3, gamma=0
blended_img = cv2.addWeighted(img1_resized, 0.7, img2_resized, 0.3, 0)

4. Segmentasyon ve Filtreleme Teknikleri

Görüntü işleme pipeline'ında nesne tespiti modellerine beslenecek verinin ayrıştırılması (segmentasyon) ve gürültülerden temizlenmesi (filtreleme), sistemin genel başarımını doğrudan etkiler.

Görüntü Eşikleme (Thresholding)

Eşikleme, ön plan nesnelerini arka plandan ayırmanın en temel yoludur. Piksel genlik değerlerini belirli bir eşik değeri ile karşılaştırarak görseli binarize etmek (siyah-beyaz yapmak) üzerine kuruludur.

  • Sabit Eşikleme: Tüm görsel boyunca tek bir global değer uygulanır.
  • Uyarlamalı Eşikleme (Adaptive): Aydınlatma farklılıklarının üstesinden gelmek için, her pikselin etrafındaki komşu piksellerinin ortalaması alınarak dinamik bir yerel eşik değeri hesaplanır. Homojen olmayan gölgeli yüzeylerde dahi nesne bütünlüğü korunur.
# Adaptive Thresholding (Mean Yöntemi, Blok Boyutu = 11, Sabit C = 8)
adaptive_thresh = cv2.adaptiveThreshold(
    gray_img, 255, 
    cv2.ADAPTIVE_THRESH_MEAN_C, 
    cv2.THRESH_BINARY, 
    11, 8
)

Düşük Geçişli Filtreler (Blurring) ve Gürültü Yönetimi

Görüntü işlemede gürültü (noise), yüksek frekanslı sinyal değişimleri olarak tanımlanır. Belirlenen bir matris (Kernel / Çekirdek) görsel üzerinde kaydırılarak merkez piksel yeniden hesaplanır.

  • Ortalama Bulanıklaştırma (Average Blur): Kernel altındaki piksellerin ortalamasını alır.
  • Gauss Bulanıklaştırma (Gaussian Blur): Gauss dağılımına uygun ağırlıklandırma yapar. Sensör ısınması veya düşük ışık koşullarından kaynaklanan Gauss Gürültüsü temizliğinde idealdir.
  • Medyan Bulanıklaştırma (Median Blur): Kernel altındaki pikselleri sıralar ve medyan (ortanca) değeri alır. Veri iletim hatası nedeniyle görsel üzerine rastgele dağılmış tam beyaz/siyah noktaları yani Tuz ve Karabiber Gürültüsünü (Salt & Pepper Noise) temizlemekte en başarılı filtredir.
# Gauss Blur
blur_gaussian = cv2.GaussianBlur(img, (3, 3), sigmaX=7)

# Median Blur (Salt & Pepper temizliği için en iyisi)
blur_median = cv2.medianBlur(sp_noisy_img, 3)

5. Yapısal Analiz ve Kenar Tespiti (Morfoloji & Gradyanlar)

Morfolojik Operasyonlar (cv2.morphologyEx)

Morfolojik operasyonlar, görsellerdeki nesne sınırlarını (şekil ve form yapılarını) düzenlemek için kullanılan işlemlerdir.

  • Erozyon (Erosion): Kernel matrisi dolaşırken pikseller beyaz değilse merkez pikseli siyah yapar. Ön plan nesnesinin sınırlarını aşındırır.
  • Genişleme (Dilation): Erozyonun tam tersidir. Nesne sınırları kalınlaşır.
  • Açma (Opening): Erozyon + Genişleme. Arka plandaki beyaz gürültüyü siler.
  • Kapatma (Closing): Genişleme + Erozyon. Nesne üzerindeki siyah delikleri kapatır.
  • Morfolojik Gradyan: Genişleme ile erozyon arasındaki farkın alınmasıdır. Nesnenin dış konturunu verir.
kernel = np.ones((5, 5), np.uint8)

# Açma Operasyonu (Morph Open - Beyaz Gürültü Temizleme)
opening_img = cv2.morphologyEx(noisy_white_img, cv2.MORPH_OPEN, kernel)

Görüntü Gradyanları & Kenar Tespiti

Kenarlar; piksellerin yoğunluğunda ani ve keskin değişimlerin olduğu sınır hatlarıdır. Matematiksel olarak ani değişimi bulmak türev almak demektir.

  • Sobel Filtresi: X yönlü filtre dikey kenarları, Y yönlü filtre yatay kenarları yakalar.
  • Laplacian Filtresi: İkinci derece türev alarak yönden bağımsız olarak her yöndeki keskin kenarları tek seferde izole eder.
# Sobel X ve Y Gradyanlarının Hesaplanması
sobel_x = cv2.Sobel(gray_img, cv2.CV_16S, dx=1, dy=0, ksize=5)
sobel_y = cv2.Sobel(gray_img, cv2.CV_16S, dx=0, dy=1, ksize=5)

# Laplacian ile Bütüncül Kenar Tespiti
laplacian = cv2.Laplacian(gray_img, cv2.CV_16S, ksize=3)
abs_laplacian = cv2.convertScaleAbs(laplacian)

6. Piksel Dağılımı ve Kontrast İyileştirme (Histogram Analizi)

Histogram Analizi (cv2.calcHist)

Görüntü histogramı; bir görselde bulunan her bir ton değeri (0-255 gri seviyesi) için kaç adet piksel bulunduğunu gösteren grafiksel bir dağılımdır. Histogram grafiğine bakarak görselin aşırı karanlık, aşırı aydınlık veya düşük kontrastlı olup olmadığı anlaşılabilir.

Maskeleme (Bitwise Operations)

Görselin tamamını işlemek yerine yalnızca ilgilendiğimiz bölgeye (ROI) odaklanmak için ikili (binary) bir maske matrisi ile orijinal görselin mantıksal VE (Bitwise AND) kapısından geçirilmesiyle yapılır.

import numpy as np

# Orijinal Görsel Boyutunda Siyah Bir Tuval (Maske) Oluştur
mask = np.zeros(image.shape[:2], dtype="uint8")
cv2.rectangle(mask, (100, 100), (300, 400), 255, -1)

# Bitwise AND İşlemi ile Görseli Maskele
masked_image = cv2.bitwise_and(image, image, mask=mask)

Histogram Eşitleme (Histogram Equalization)

Kötü ışık şartlarında çekilmiş görseller genellikle düşük kontraste sahiptir. Piksel genlikleri sadece 120-180 gibi dar bir bantta sıkışır. Histogram Eşitleme (cv2.equalizeHist), bu dar dağılımı Kümülatif Dağılım Fonksiyonu kullanarak 0-255 dinamik aralığının tamamına yayar. Böylece görseldeki zıtlık artar ve gizli detaylar belirginleşir.

# Düşük kontrastlı görüntüyü netleştirme
equalized_img = cv2.equalizeHist(gray_img)

7. Sonuç ve Gelecek Adımlar

Sayısal görüntü işleme (Digital Image Processing), derin öğrenme ve yapay zeka sistemlerinin en kritik ön işleme (pre-processing) safhasıdır. Bu rehber boyunca ham sinyal ve piksel verisinden başlayarak; veri akışlarının yönetilmesini, matris seviyesinde geometrik dönüşümleri, gürültü temizlemeyi, morfolojik yapılandırmayı, kenar analizini ve kontrast eşitlemeyi adım adım teorik ve pratik boyutlarıyla ele aldık.

Geliştirdiğimiz tüm bu tekniklerin temel amacı; karmaşık yapay zeka modellerine besleyeceğimiz veriyi yüksek sinyal-gürültü oranına ulaştırmaktır. Bir sonraki aşamamız OpenCV ile Nesne Tespiti ve Takibi olacaktır. Kontur Analizi, Haar Cascade veya Tracker algoritmalarını bu temel üzerine inşa edeceğiz.

💻 GitHub Repository ve Uygulama Kodları

Bu makale serisinde ele alınan tüm teorik konuların Python ortamında yazılmış kaynak kodlarına, örnek görsellere, gürültü simülasyonlarına ve veri setlerine GitHub depom üzerinden ulaşabilirsiniz:

GitHub Reposu: Rasittekin18 / 7-Image_Processing_with_OpenCV

Sorularınız, katkılarınız veya projelerinize dair fikir alışverişi için benimle iletişime geçmekten çekinmeyin!

Raşit Tekin
Yapay Zeka & Veri Bilimi Mühendisi
rasittekin.com | GitHub

Yorum bırakın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir