Makale Özeti

Bu makalemizde görüntü işlemede sıkça kullanılmakta olan keskinlik arttırılması için kullanılan yöntemleri incelemeye çalışacağız.

Makale

C#



Merhabalar;

Bu makalemizde görüntü işlemede sıkça kullanılmakta olan keskinlik arttırılması için kullanılan yöntemleri incelemeye çalışacağız.

Görüntülerimizi negatif değerlere yaklaştırırken netlik ayarları bozulmuş resimleri karşımızda bulabilmekteyiz.Bu resimleri istediğimiz görüntülere dönüştürme yöntemleri kafamızda sürekli olarak soru işareti olarak kalmıştır.Bu sorunları çözmeye için yazılımcılar farklı yöntemler üreterek çözüm bulmaya çalışmıştırlar.

Bu yöntemler araştırılırken ilk başka akla gelen bütün resmi işlemek olmuştur.Fakat bütün resmi işleyerek tam anlamıyla başarı sağlanamayacağını görmüşlerdir.Çünkü bütün resmin işlenmesi keskinlik arttırılması yönteminde değerlerin ortalmasını alıpta sonuç üretmek gibi oluyor.Bu da hem istenen sonuçtan uzak hem de performans açısından oldukça yavaş olan bir çözüm oluyordu.

Akademisyenlerin ve yazılımcıların uzun araştırmaları sonucunda bulunan en doğru yöntem şu anda da kullanılmakta olan parçalara bölerek yapılan yöntemdir.Bu yöntemin bulunması hem bellek optimizasyonu sağlarken hemde resimlerimizde istediğimiz sonuçları almamızı sağlamıştır.

Programımızı oluşturmadan önce yapmamız gereken bir özellik var.Eğer bu işlemi yapmazsak beyaz bir resmi başka bir renge çevirmek yaklaşık 4 saniye gibi bir süre almaktadır ki bu süre günümüz bilgisayarları için gerçekten çok uzun bir süre olacaktır.Bu durumda kullanıcıların bizim oluşturduğumuz programı kullanmamaları gibi istenmeyen bir sonuçla karşılaşmış oluruz.Kullanacağımız bu yöntemin adı Unsafe özelliğidir.Unsafe kod optimizasyonunu sağlamakta ve projemize bellekte öncelik tanıyarak performansını arttırmaktadır. Unsafe özelliğinin nereden açılacağını bilmeyenler için Project-->En altta olması gereken (projeismi+properties)-->Build-->Allow unsafe code ‘u tiklediğiniz zaman unsafe özelliğini açmış olacağız ve projemiz çok büyük boyutlu görüntülerde bile işlem konusunda zaman kaybına yol açmayacaktır.

Unsafe
{


byte * src = (byte *) srcData.Scan0.ToPointer();
byte * dst = (byte *) dstData.Scan0.ToPointer();


src += stride;

dst += stride;


Değişkenlerimizi tanımladıktan sonra src ve dst adında resmimizin alanları tutulacak ve işlenecek olan bölgelerin point olarak tutulmasını sağlayacaklardır.

Belleğimizde yer talep ettikten sonra asıl önemli nokta olan görüntüyü işleyeceğimiz yönteme sıra gelmiştir.

Bu yöntemi nasıl uygulayabiliriz diye kendimize bir kaç soru sormamız gerekiyor aslında.Örneğin bir resmi tamamen işleme soktuğumuz taktirde unutmayalım ki istediğimiz sonucu alamayacağız.Çünkü görüntünün her noktası aynı değerde değil ve keskinlik ayarları ve homojensel değerleri birbirinden farklıdır.

Daha değişik bir yöntem üzerinde durmak gerekirse.İlköğrenim zamanımızda hatırlarsınız hepimiz harita çizmişizdir.Haritayı gözel çizebilmek için iki yöntemimiz vardı.Bunlardan birincisi kağıdı kitabın üzerine koyarak çizmekti(Buna kopya diyorduk ve kolaya kaçmak oluyordu).İkinci ise kitaptaki haritayı belirli parçalarak bölerek ölçeklendirme yapmaktı.Bizde bu ölçeklendirme yöntemine benzer bir yöntemi takip ederek istediğimiz sonuca ulaşmaya çalışacağız.

Görüntümüzü incelerken belirli noktalarını alacağız.Örneğin sağ üst köşesi, ortası, sol alt köşesi gibi.Bu işlemi yaparken görüntümümüzün maksimum değerlerini tutarak bu değerleri for düngüsü içerisinde dündürerek işlemimizin sonucunu getirmiş olacağız.

Aşağıdaki kod parçacığında kullanılan yükseklik ve genişlikler tanımlanırken toplam değerlerinden 1 eksiltilerek yapılmıştır.Bunun sebebi arttırılan değerlerimiz maksimum noktalara eş olamamasıdır.Uygulanan tanımlama ve yöntem alt kısımda belirtilmiştir.

int widthM1 = width - 1;
int heightM1 = height - 1;



for (int y = 1; y < heightM1; y++)
{
src ++;
dst ++;

// For’a girecek olan sistem.
for (int x = 1; x <widthM1; x++, src ++, dst ++)
{
max = 0;
v = *src;

//sol - üst
d = v - src[-stride - 1];
if (d < 0)
d = -d;
if (d > max)
max = d;
// üst
d = v - src[-stride];
if (d < 0)
d = -d;
if (d > max)
max = d;
// sağ-üst
d = v - src[-stride + 1];
if (d < 0)
d = -d;
if (d > max)
max = d;
// sol
d = v - src[-1];
if (d < 0)
d = -d;
if (d > max)
max = d;
// sağ
d = v - src[1];
if (d < 0)
d = -d;
if (d > max)
max = d;
// sol - alt
d = v - src[stride - 1];
if (d < 0)
d = -d;
if (d > max)
max = d;
// alt
d = v - src[stride];
if (d < 0)
d = -d;
if (d > max)
max = d;
// sağ - alt
d = v - src[stride + 1];
if (d < 0)
d = -d;
if (d > max)
max = d;

*dst = (byte) max;
}
src += offset + 1;
dst += offset + 1;

}


Yukarıda yaptığımız işlemeleri açıklamak gerekirse.

For döngülerimize dikkat edersek yükseklik ve genişlik ile ilgili değerlerimizi arttırmakta.Onun dışında ikinci For ‘un altında arttırılan src değeri başka bir değişkene atanır ve bu atanan değişkende kilit noktalardan çıkartılarak istenen sonuca ulaşabilmekteyiz.İşlemin en sonunda ise tutulan değerlerimiz ve görüntümüz serbest bırakılarak istenen sonuç elde edilir.

Açıkladığımız kod homojenlik ile ilgili temel kod parçalarını açıklamaktadır.Ek olarak bu yöntemden yararlanılarak üzerinde ufak değişiklikler yapmamız sonucunda Ayrımlılık ve Parlak Ayrımlılık ile ilgili yöntemleride ulaşılabilmektedir.

Yukarıda açıklamış olduğumuz sınıfı kullanarak oluşturalan bir proke üzerinden yapılmış olan bir projeden alınmış görüntüler aşağıdadır.


Keskinlik arttırılması yöntemi gönderilecek olan görüntünün orjinal hali.


Ayrımlılık işlemi sonucunda elde edilen sonuç.


Homojenlik işlemi uygulandıktan sonra elde edilen sonuç.


Parlak ayrımlılık işlemi sonuçlandıktan sonra elde edilen sonuç

Umarım yararlı olmuştur.

İyi çalışmalar...

Turhal TEMİZER

Kaynaklar
Karadeniz Teknik Üniversitesi Görüntü İşleme Ders Notları ve Dönem Sonu Projesi