Posted under C# (csharp)
Bu yazıda Gdi kütüphanesi ile basit görüntü işleme tekniklerinin, bir resim üzerinde uygulanmasını ele alacağız. Bu teknikleri kullanarak resimler üzerinde gamma - gray scale - brightness gibi efektlerin nasıl uygulanacağından ve bu efektlerin özelliklerinden bahsedeceğiz. Ayrıca bu sayede bitmap yapısınada kısaca bir göz atmış olacağız. Aşağıda yapılmış basit bir uygulamanın resmini görmektensiniz. Birazdan bu efektlerin nasıl yapıldığını açıklayacağız.
Efektlerin bir resim üzerinde uygulanması şu şekildedir; ilk olarak resmin pixellerini elde ederiz ve bunları sistematik bir şekilde matemetiksel işlemler uygulayarak değiştiririz. Burada bahsedeceğimiz efektler sistematik belli formüller dahilinde yapılan efektlerdir.Fakat sistematik yapılmayan efektlerde vardır mesela noise efekti. İlerki yazılarımda basit bir filitre mantığından bahsederken bu efekti de gözden geçireceğiz.
Efektlerden bahsetmeden önce bir resim üzerinde pixel bazında nasıl değişiklik yapılacağından bahsedelim ve biraz da bitmap yapısına değinelim. Aşağıdaki kodda basit bir bitmapin nasıl oluşturulacağını görebiliriniz.
CBitmap bitmap; bitmap.CreateCompatibleBitmap (&dc, 100, 100); |
Bitmap pixellerden oluşan bir yapıdır. Pixel ise bir renk tonudur. Biz bu uygulamada 24 bit renk derinliğini kullanacağız. Yani bunun için tonları 0-255 arasında olabilecek 3 renge ihtiyacımız var. Bunlar kırmızı,yeşil ve mavi renkleridir. Aşağıda bir pixelin renk değerlerinin nasıl elde edildiğinden bahsedeceğiz. Mfc de bir bitmap oluşturmak için hazır bir sınıf bulunmaktadır (CBitmap).Boyutları belli olan bir bitmap yaratmak için bu sınıfın CreateCompatibleBitmap adlı fonksiyonunu kullanırız.Bu fonksiyoni,boyutlarıı belirleyebileceğimiz kullanılabir bir bitmap oluşturmamıza izin verir.Fakat bitmap üzerinde pixel bazında işlemler yapabilmek için bu sınıf yeterli değildir.Bunun için bir Dc nesnesine ihtiyaç vardır.İşte bunun için CDC sınıfından bir nesne oluşturmamız gerekir.Bunu şu şekilde yapabiliriz.
CDC dcMem; //Bitmap i seçmek için kullanacağımız dc dcMem.CreateCompatibleDC (&dcScreen);//dcScreen programın an dc nesnesi dcMem.SelectObject (&bitmap); //bitmap i seçiyoruz |
Burda CDC sınıfından türettiğimiz dc nesnesini kullanabilmemiz için bunu başka bir dc nesnesi ile bağlantılı şekilde yaratmamız gerekir.Burda dc nesnesini oluşturmak için CreateCompatibleDC fonksiyonundan yararlandık bu fonksiyon parametre olarak başka bir dc nesnesi istemektedir.Bunun için asıl çizim yaptığımız dc nesnesini kullandık(dcScreen).Sonra istediğimiz bitmap i oluşturduğumuz bu nesneye seçebiliriz.Bir bitmap i görünüme çizmek için ise CDC sınıfının BitBlt fonksiyonunu kullanablirsiniz.Aşağıdaki uygulamasını görebilirsiniz.
dcScreen.BitBlt (0, 0, 100, 100,&dcMem, 0, 0, SRCCOPY); |
Artık dc nesnemizi yarttığımıza göre artık pixel bazında işlemlere geçebiliriz.Bu işlemler için CDC sınıfının GetPixel() ve SetPixel() fonksiyonlarını kullanabiliriz.GetPixel() fonksiyonu nu bitmap ten pixel değerlerini almak için kullanacağız.Bu fonksiyon dönüş değeri olarak bir renk değeri dönderir ve bu değeri matematiksel işlemlerle isteğimiz şekilde değiştirdikten sonra bu değerleri, pixel değerlerini değiştirmek için kullanacağımız SetPixel() fonksiyonuna parametre olarak geçirebiliriz ve böylece resim üzerinde istediğimiz değişikliği yapmış oluruz.Pixellerden elde ettiğimiz değerler renk değeridir ve bu mfc de COLORREF yapısı ile tanımlanmıştır.Bu yapı ya değer verilirken RGB makrosunu kullanırız.RGB makrosu 3 adet integer değer içermektedir.Bunlar Red,Green,Blue değerleridir.Şimdi bir bitmap e bir resmin nasıl okunacağını görelim.
bitmap.m_hObject=(HBITMAP)LoadImage(theApp.m_hInstance,”resim.bmp”,IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE | LR_DEFAULTSIZE);
|
Bunun için LoadImage fonksiyonunu kullandık.Fonksiyonun ikinci paremetresine istediğimiz bmp formatındaki resmin ismini verdik.Fonksiyonun diğer parametreleride değinmeyeceğim.
Bu konularada değindikten sonra isterseniz bir bitmap ten pixel değerlerini nasıl elde edilebileceğinden bahsedelim.Yukarda bahsettiğimi gibi bunun için GetPixel() fonksitonunu kullanacağız.Aşağıda kodu görebilirsiniz.
COLORREF color; for(int y=0;y<100;y++)
{
for(int x=0;x<100;x++)
{
color=dcMem.GetPixel(x,y);
int r=GetRValue(color);
int g=GetGValue(color);
int b=GetBValue(color);
r+=1;
g+=1;
b+=1;
color=RGB(gray,gray,gray); usedc.SetPixel(x,y,color);
}
}
|
İlk olrak bu işlemi iki tane for döngüsü içerisinde yaptık,Çünkü yukarda yarattığımız bitmap in boyutları 100,100 dü.Yani bizim resmimiz 10.0000 adet pixel değeri içermektedir.Pixellerin renk değerini sırayla GetPixel() fonksiyonunu kullanarak COLORREF ten türettiğimiz color değişkenimize aldık.Bir aşağı satırda ise GetRValue(),GetGValue(),GetBValue() fonksiyonlarını kullanarak pixel renk değerlerimizi integer değeri olarak elde ettik.Bu aşamadan sonra renk değerlerine istediğimiz işlemleri uygulayabiliriz.Burda sadece renk değerlerini 1 er artırdık ve bitmap i yeni renk değerleriyle yeniden oluşturduk.
İşimize yarayacak yapılardan ve fonksiyonlardan bahsettikten sonra artık efektleri incelemeye başlayabiliriz.Sırasıyla gray scale - gamma -brightness efektlerinden bahsedeceğim.
Gray Scale Efekti
orjinal resim
gray scale efekti uygulanmış resim
Yukardada resimdede gördüğünüz gibi resimden elde ettiğimiz pixel renk değerlerinden kırmızı,yeşil ve mavi yi ortak bir işleme sokarak tek bir renk elde ediyoruz ve yeni renk değerlerini kullnarak pixel pixel bitmap i tekrar oluşturuyoruz.Bu işlemi gerekleştirmek şu formülden yararlandık;
gray=0.299 * red + 0.587 * green + 0.114 * blue
Burada renk değerlerini belirlenmiş sabit sayısal değerlerle çarparak (0,299,0,587,0,114) ortak bir renk elde ettik.İki tane daha gray scale yöntemi var bunlarında formüllerini vermek istiyorum.Bu formüllerde gene aynı sonucu vermektedir.
gray=0.2125 * red + 0.7154 * green + 0.0721 * blue gray=0.5 * red + 0.419 * green + 0.081 * blue
Şimdi bu işlemin kodla uygulanışına bakalım.
for(int y=0;y |
Gamma Efekti
orjinal resim
gamma efekti uygulanmış resim
gamma efekti uygulanmış resim
Gama değerleri resimden elde ettiğimiz pixel değerlerindeki renklerden bağımsız şekilde oluşturulur ve gama için gerekli olan renk değerleri 0.2 ile 5 arsında değişir.Gama değerleri 256 tanedir (0-255).Bunları elde etmek için şu formülü kullanırız.
red[i]=min(255, (int) ( (255.0 * pow(i/255.0, 1.0/r)) + 0.5 ) );
green[i]min(255, (int) ( (255.0 * pow(i/255.0, 1.0/g)) + 0.5 ) );
blue[i]min(255, (int) ( (255.0 * pow(i/255.0, 1.0/b)) + 0.5 ) );
0 dan 256 ya kadar bu değerleri buluruz ve rengimizin gama değerini bulmak için şöyle yaparız.Bitmap ten elte ettiğimiz renk değerleri şunlar olsun m_red,m_green,m_blue ve yeni renk değerleri elde etmek için renk değerleri index olacak şekilde oluşturduğumuz gama değerleri dizisinden alırız.
m_red=red[m_red]; m_green=green[m_green]; m_blue=blue[m_blue]; Bu işlemi kodla şu şekilde yapabiliriz.
//gama değerleri
int red[256];
int green[256];
int blue[256];
COLORREF color; //renkleri tutacağımız değişken int r,g,b; UpdateData(); //kontrollerden verileri alıyoruz for(int i=0;i<256;i++) { //gama değerlerini hesaplıyoruz //m_vred,m_vgreen ve m_vblue programdaki slider barlardan alınan sayısal değerlerdir red[i]=min(255, (int) ( (255.0 * pow(i/255.0, 1.0/(m_vred))) + 0.5 ) ); green[i]=min(255, (int) ( (255.0 * pow(i/255.0, 1.0/(m_vgreen))) + 0.5 ) ); blue[i]=min(255, (int) ( (255.0 * pow(i/255.0, 1.0/(m_vblue))) + 0.5 ) ); } for(int y=0;y
r=GetRValue(color);
g=GetGValue(color);
b=GetBValue(color);
color=RGB(red[r],green[g],blue[b]);//renklerin gama değerini alıyoruz
usedc.SetPixel(x,y,color);
}
}
|
Brightness Efekti
orjinal resim
brightness efekti uygulanmış resim
brightness efekti uygulanmış resim
Uygulanması en kolay efekttir.Yeni renk değerlerini oluşturmak için kendinize bir aralık belirlersiniz mesela (-100) - (100) arasında.Sonra bu aralıktan elde edilen değerleri bitmap tan aldığınız renk değerlerine ilave edersiniz.Sonrada elde ettiğimiz yeni renk değerlerini bir sınamadan geçiririz. Eğer değer 0 da küçükse 0, 255 ten büyükse 255 değerlerini veririz.
m_red+=m_brightness; m_green+=m_brightness; m_blue+=m_brightness;
Görüldüğü gibi uygulaması çok basittir.Eğer istersek her renk için ayrı bir parlaklık efekti uygulayabiliriz.Benim yazdığım kod ta her renk için ayrı parlaklık efekti uygulanmasına izin verilmiştir.Bu işlemin kod uygulamasını aşağıda inceleyebilirsiniz.
COLORREF color;
int r,g,b;
UpdateData();
for(int y=0;y
r=GetRValue(color);
g=GetGValue(color);
b=GetBValue(color);
//m_pos slider bardan aldığımız posisyon değeri
int brighnes_r=(int)(r+m_pos);
int brighnes_g=(int)(g+m_pos);
int brighnes_b=(int)(b+m_pos);
//m_kırmızı,m_yesil,m_mavi checkboxlardan alınmış bool tipinde değerler
if(m_kirmizi)
{
if(brighnes_r<0) brighnes_r=0;
if(brighnes_r>255) brighnes_r=255;
}
else
{
brighnes_r=r;
}
if(m_yesil)
{
if(brighnes_g<0) brighnes_g=0;
if(brighnes_g>255) brighnes_g=255;
}
else
{
brighnes_g=g;
}
if(m_mavi)
{
if(brighnes_b<0) brighnes_b=0;
if(brighnes_b>255) brighnes_b=255;
}
else
{
brighnes_b=b;
}
color=RGB( brighnes_r, brighnes_g, brighnes_b);
usedc.SetPixel(x,y,color);
}
}
|
Bu yazımızında sonuna geldik.Görüntü işleme çok geniş bir konudur ve çok farklı alanlarda kullanılabilir.Biz bu yazıda sadece bir kaç görüntü efektinden bahsettik.Diğer yazılarımdada bu konulara daha fazla değineceğim ve diğer efektlerinde uygulanmasını göstereceğim.Genelde hep formüller kullanılarak işlem yapıldığından dolayı bu konular hakkında ayrıntılı anlatımlı bir kaynak fazla bulamazsınız.Ama Gdi ve gdi+ ile ugulamalar hakkında şu kitaptan ve siteden yararlanabilirsiniz. www.amazon.com www.codeproject.com İYİ ÇALIŞMALAR….
fatih on 15 May 2008 at 06:05 #
ben bu kanuda makalenın ıcın gercekten tessur edeım elınıze saglık
ama aklımatakılan bı soru var bu yazdıgınız kodlar c# da calısıyomu??
ben denemdım calısmadı variable ları tanımadı acama kutuphane mı eklememız gerekıyo
kısa surede maıl atarsanız sevınırım
ıyı calısmalar..