Daha önce "burada" genel olarak bahsettiğim ve kullanılacak kod bloğunu tanıttığım "C# ile Görüntü İşleme"yi bir kaç örnek üzerinde anlatmaya çalışacağım.Bir görüntü üzerinde yapılabilecek işlemleri noktasal, alansal, toplamsal, biçimsel gibi alt kategorilere bölebiliriz.
Öncelikli olarak noktasal işlemlerden bahsedersek, noktasal işlemler; görüntü üzerinde gözek gözek dolaşıp, her gözekin sadece kendi değerini değiştirdiğimiz işlemlerdir. Örnek olarak parlaklık(brightness) , zıtlık(contrast), gritona çevirme, negatif ve eşikleme gibi işlemleri verebiliriz. Alansal işlemler ise sadece bir gözekle değil birbirine komşu birkaç gözekle yapılan işlemlerdir. En bilinen örneği filtrelerdir. Örneğin bir resme medyan filtresi uygulamak istediğimizde seçilen yapısal elemana göre (3x3 veya 5x5) o bölgedeki tüm gözeklerin değeri hesaplanıp yapısal elemanın ortasındaki değere yazılır. Biçimsel işlemler, resmin renk değerlerinde değil de biçiminde yapılan değişikliklerdir. Balık gözü(fish eye), girdap(twirl) ve gözekleme(pixelate) gibi. Toplamsal işlemlere de Fourier dönüşümünü örnek verebiliriz.
Noktasal işlemlerin birkaçından genel olarak bahsedip sadece parlaklık üzerinde duracağım. Diğer işlemlere de ilerleyen günlerde Kod Kütüphanesinde yer vereceğim.
Bir gözeğin renk değerlerinin 0 ile 255 arasında değiştiğinden bahsetmiştik. Değerler 255 e yaklaştıkça o gözeğin parlaklığı artar. Bunun için bir resmin parlaklığını artırmak için , resmin tüm gözeklerinin renk değerlerini artırmalıyız. Kod üzerinde açıklarsak;
(daha basit ve anlaşılır olduğu için 32bitlik formatı tercih ettim.)
public Bitmap parlat(Bitmap resim, int değer)
{
unsafe
{
BitmapData bmpdata = resim.LockBits(new Rectangle(0, 0, resim.Width, resim.Height),
ImageLockMode.ReadWrite, PixelFormat.Format32bppArgb);
byte* p = (byte*)bmpdata.Scan0;
for (int i = 0; i < bmpdata.Height; i++)
{
for (int h = 0; h < bmpdata.Width; h++)
{
p[0] =Convert.ToByte( p[0]+değer );
p[1] =Convert.ToByte( p[1]+değer );
p[2] =Convert.ToByte( p[2]+değer );
p += 4;
}
}
resim.UnlockBits(bmpdata);
return resim;
}
}
Burada 'resim' gözek gözek dolaşılmakta ve renk değerleri, girilen 'değer' parametresi kadar artırılmaktadır. Yalnız burda dikket edilmesi gerekilen nokta renk değerlerinin 0-255 arasında değişmesidir. Eğer değerler bu sınırı geçerse program hata verecektir. Onun için her artırmada değerler kontol edilip 255'i geçenler 255'e, 0'ın altına inenlerde 0'a eşitlenmelidir. Düzeltilmiş kısım ;
for (int i = 0; i < bmpdata.Height; i++)
{
for (int h = 0; h < bmpdata.Width; h++)
{
//mavi için
if (p[0] + değer > 255) p[0] = 255;
else if(p[0] + değer < 0 ) p[0] = 0 ;
else p[0] =Convert.ToByte( p[0]+değer );
//yeşil için
if (p[1] + değer > 255) p[1] = 255;
else if (p[1] + değer < 0) p[1] = 0;
else p[1] = Convert.ToByte( p[1] + değer);
//kırmızı için
if (p[2] + değer > 255) p[2] = 255;
else if (p[2] + değer < 0) p[2] = 0;
else p[2] = Convert.ToByte(p[2] + değer);
p += 4;
}
}
Bu yöntem pekde doğru bir algoritma olmayıp, görüntü işlemenin matnığını anlatmak için verdim. Parlaklık için çeşitli fonksiyonlar internette bulunabilir.
Diğer noktasal işlemlerden biraz bahsedecek olursak; bir görüntünün tersini(negatifini), tüm gözeklerin renk değerlerini 255 den çıkararak elde ederiz.
for (int i = 0; i < bmpdata.Height; i++)
{
for (int h = 0; h < bmpdata.Width; h++)
{
p[0] = Convert.ToByte(255 - p[0]);
p[1] = Convert.ToByte(255 - p[1]);
p[2] = Convert.ToByte(255 - p[2]);
p += 4;
}
}
Bir resmi gritonlarına çevirmek için kırmızı, yeşil, mavi renk değerlerinn ortamasını alıp üç rengede bu değeri atıyarız. Yine bu yönteme göre daha bir yöntem var olup bu yöntem, her rengi belli bir oranda işleme katar.
for (int i = 0; i < bmpdata.Height; i++)
{
for (int h = 0; h < bmpdata.Width; h++)
{
byte ort = Convert.ToByte((p[0] + p[1] + p[2]) / 3);
p[0] = p[1] = p[2] = ort;
p += 4;
}
}
Daha başka bol kodlu günlerde görüşmek üzere...