Yazan : Şadi Evren ŞEKER

Temel olarak bir programlama dilinde resim işleme işlemleri için iki fonksiyon gerekir.

Yani aslında resim üzerinde yapılan herşey, resmi oluşturan imgecikler üzerinde yapılmaktadır.

Bu yazıda CSharp programlama dili kullanılarak basit bir histogram çıkarma ve resme gama doğrulaması (Gamma correction, gamma encoding) uygulanması anlatılacaktır.

Öncelikle resim işleme işlemleri sırasında kullanılcak olan arayüzün tasarlanması ile başlayacağız. Basit bir picturebox (resim kutusu) ve üç düğme bu çalışma için yeterli olacaktır. (Düğmelerden birisi resmin histogramı için diğeri de gama doğrulaması için kullanılacak)

Planımız şu şekilde:

Form yüklenince, yani program ilk çalıştığı anda bir dosya açma diyaloğu (open file dialog) belirecek. Kullanıcı bu diyalog ile bir resim dosyası seçecek ve ardından birinci düğme ile histogramı çıkarabilecek ikinci düğme ile de gama doğrulaması yapabilecek.

Bu uygulamada Visual C# 2008 express sürümü kullanılacaktır.

Uygulamanın görsel tasarımı:

Uygulama tasrımı sırasında tek bir form kullanılacaktır. Formu aşağıdaki şekidle tasarlayabilirsiniz:

csharpimage1

Yukrıda görüldüğü üzere 3 button ve bir adet picturebox nesnesi forma yerleştirilmiştir. Ayrıca bileşenlerin isimleri yukarıdaki şekilde yazılıdır. Formun görsel tasarımı aşağıda verilmiştir.

csharpimage2

yukarıdaki şekilde butonlara isim verdikten sonra kodlamaya başlayabiliriz.

Öncelikle dosya açma diyaloğu için kodumuzu yazalım. Resim yükle isimli buton1 tıklaması için aşağıdaki kodu yazıyoruz:

private void button1_Click(object sender, EventArgs e)
{
OpenFileDialog dialog = new OpenFileDialog();
dialog.Filter =
“JPEG Dosyaları|*.jpg|Bütün Dosyalar (*.*)|*.*”;
dialog.InitialDirectory = “.”;
dialog.Title = “Bir resim dosyası seçiniz”;
if (dialog.ShowDialog() == DialogResult.OK)
{
pictureBox1.ImageLocation = dialog.FileName;
}
}

Yukarıdaki kodda basit bir dosya açma diyaloğu (open file dialog) kullanılmış ve jpeg dosyaları filitrelenmiştir. Ayrıca dosyanın seçilmesi ve tamam düğmesine basılması sonucunda pictureBox1 nesnesine dosya yüklenmiştir.

csharpimage3

Yukarıda, bu kod sonucunda çalışan açma diyaloğu görüntülenmektedir. Kullanıcı bir resim dosyası seçip Aç düğmesine basınca yukarıdaki kodda bulunan if bloğu çalışacak ve açılan dosya pictureBox1 nesnesinde görüntülenecektir:

csharpimage4

Yukarıda, örnek olarak açılmış ve görüntülenen bir resim bulunmaktadır.

Histogram çıkarımı

Yukarıdaki form tasarımını bitirdikten sonra resim işleme adımlarımızdan ilki olan histogram çıkarımına başlayabiliriz. Amacımız yukarıdaki bölümde anlatılan resim yükleme işleminin sonunda yüklenen resmin RGB (red green blue, kırmızı yeşil mavi) değerlerine göre histogramını çıkarmaktır.

Histogram çıkarımı ve resim işleme adımlarının hemen hepsinde gereken bir resme imgecik imgecik (pixel) erişmeyi sağlayan, C# altındaki bitmap sınıfıdır. Bu sınıfı kullanabilmek için öncelikle picturebox içerisinde yüklü olan resmi bitmap’e çevirmemiz gerekir.

Bu işlemler için tasarımımızdaki ikinci düğmeyi kullanıyoruz ve düğmenin arkasını aşağıdaki kodu yazıyoruz:

private void button2_Click(object sender, EventArgs e)
{
Image img = pictureBox1.Image;
Bitmap bmp = new Bitmap(img);
int[] kirmizi = new int[256];
int[] yesil = new int[256];
int[] mavi = new int[256];

for (int i = 0; i < bmp.Size.Height; i++)
for (int j = 0; j < bmp.Size.Width; j++)
{
Color renk = bmp.GetPixel(i, j);

kirmizi[renk.R]++;

yesil[renk.G]++;
mavi[renk.B]++;

}

Yukarıdaki kodda basitçe bir bitmap sınıfından (class) bmp isimli bir nesne (object) tanımlanmıştır. Bunun için öncelikle pictureBox nesnesinden Image değeri alınmış sonra bu Image değeri bir bitmap’e yüklenmiştir.

Ardından 3 adet dizi tanımlıyoruz. Bu diziler sırasıyla işleyeceğimiz imgeciklerin (pixel) kirmizi, yesil ve mavi değerlerini okuyacak dizilerdir. Yani resmimizdeki her imgeciğin sahip olduğu kırmızı değeri için, o değerin dizideki sayısını 1 arttırıyoruz. Burada bilinmesi gereken bir nokta bitmap resimlerde bir renk kodu 0 ile 255 arasında bir değerdir. Dolayısıyla dizilerimiz 256 boyutunda tanımlanmıştır ve sonuçta her imgeciğin sahip olduğu kırmızı kodu kirmizi dizisindeki ilgili değeri bir arttırmaktadır. Bu durum diğer renkler içinde geçerlidir.

Kodun devamında dosyaya kaydetme işlemlerini yazıyoruz:

SaveFileDialog sfd = new SaveFileDialog();
sfd.InitialDirectory = “.”;
sfd.Title = “Histogramin kaydedilecegi dosyayi belirtin”;
if (sfd.ShowDialog() == DialogResult.OK)
{
StreamWriter fwriter =
File.CreateText(sfd.FileName);

for (int i = 0; i < 256; i++)
{
fwriter.Write(“” + kirmizi[i] + “|” + yesil[i] + ” | ” + mavi[i] + “n”);
}

fwriter.Close();
}

Yukarıdaki kod basit bir şekilde bir savefiledialog oluşturuyor yani dosyanın kaydedileceği yeri ve ismi alıyor. Kullanıcı tamam düğmesine bastıktan sonra bir StreamWriter ile dosyayı açıyor ve içerisine dizimizdeki değerleri satır satır basıyrouz.

Yukarıdaki kodun çalışması sırasında dosya işlemleri ile ilgili System.io paketinin yüklü olması gerekir bunun için kodun başına

using System.io;

satırını eklemeyi unutmayınız.

csharpimage5

Yukarıdaki diyalogta ben “deneme.txt” dosyası ismi verdim ve histogram değerleri bu dosyanın içerisine kaydedildi. Yüklü olan resme göre aşağıdakine benzer bir sonuç çıkabilir:

csharpimage6

Yukarıdaki dosyada 256 adet satır bulunmaktadır ve kodumuzdan da hatırlanacağı üzere her satır ilgili renk kodunun değerini tutmaktadır.

Örneğin kırmızı değerinin 0 olduğu 3297 imgecik bulunduğunu yukarıdaki dosyadan anlayabiliyoruz.

histogramexcel

Dosyadaki bu değerleri excel programı ile çizdiğimizde yukarıdakine benzer bir grafik çıkıyor. Bu grafik ve değerler kullanılan resim için farklılık gösterebilir. Sonuçta her resimdeki renk değerlerinin dağılımı farklı olacaktır.

windowsformsapplication21

Programın buraya kadar olan kısmını içeren csharp projesini yukarıdaki bağlantıya tıklayarak indirebilirsiniz.

Yorumlar

  1. equyak

    Öncelikle güzel anlatımın için tşkrlr.. mükemmel bi şekilde hem çok güzel ve açıklayıcı, hemde çok sade bi şekilde konuyu kavratan bir örnek vermişsin..

    ama siteye yazdığın
    Color renk = bmp.GetPixel(i, j);
    kod satırında hata verior program. Doğrusu
    Color renk = bmp.GetPixel(j, i); şeklinde olmalı. Yanlışı debug ile çalışırken buldum ama kodun doğrusunu senin indirmek için linkini verdiğin proje dosyasından karşılaştırırken buldum.. proje dosyasını indirmeden projeyi sitedeki kodlardan yapan arkadaşlar bu hatayı düzelterek yaparlarsa sorunsuz çalışıor program..

  2. Şadi Evren ŞEKER Article Author

    Sorunun cevabı zaten yukarıdaki bulunuyor.

    Color renk = bmp.GetPixel(i, j);

    şeklindeki satırda geçen komut ile ilgili pikselin (i,j koordinatlarındaki) değerini renk olarak okursunuz. Daha sonra bunu istediğiniz bir diziye atabilirsiniz. Örnek kodu aşağıda veriyorum:

    Color dizi[][] = new Color[bmp.Size.Height][bmp.Size.Width];
    for(int i = 0;i

  3. oculos

    iyi gunler kolay gelsın..bırsey sorablıır mıyım acaba pıksel pıksel alıp o pıksellerı karsılastırma ımkanımız var mı ? varsa nasıl yapılıyor bıraaz yardımcı olabılırmısınız rıca etsem..bırde java bılgısı olan benımle ıletısıme gecerse sevınırım..rcpszn1001@gmail.com maıl adresım bana yardımcı olabılecek varsa cok ama cok sevınırım sımdıden kolay gelsın tekrar ıyı aksamlar..

Bir cevap yazın

E-posta hesabınız yayımlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir