RGB-HSV Uzay Dönüşümü

HSV renk uzayı renkleri içerdiği RGB değerlerine göre değilde Hue (Renk Özü), Saturation (Doygunluk) ve Value(Parlaklık) değerlerine göre belirten bir renk uzayı türüdür. 1978 yılında Alvy Ray Smith tarafından RGB uzayına göre insan görme sistemine daha benzer bir yapı oluşturmak amacıyla tanımlandı. Yandaki silindirden de görüleceği üzere H değeri 0-360° arasında değişirken renklerin öz değerleri değişir. Ancak H sabit olarak seçilir ve diğer değerler (S V) 0-100 arasında değiştirilirse aynı rengin farklı doygunluk ve parlaklıktaki değerleri elde edilir. Bu özellğinden dolayı HSV renk temelli ayırma işlemlerinde sıklıkla tercih edilir. İki uzay arasındaki dönüşüm doğrusal olmayan bir bağlantı ile gerçekleştirilir.

Burada dikkat edilmesi gereken nokta RGB değerlerini 0-1 arasına indirilmesi gerekliliğidir. Her pikselin değeri 255 ile bölünerek normalize edildikten sonra aşağıdaki formüllle HSV değerleri bulunabilir.


Bulunan değerler yine 0-1 aralığında olacağından H değeri 360, diğer değerler ise 100 ile çarpılarak gerçek değerlere ulaşılabilir. Dönüşüm için yazılan C++ kodu aşağıda verilmiştir.
double mx=max(r,g,b);
double mn=min(r,g,b);
HSV h;

if(mx==mn) { h.hue=0; }
else if(mx==r && b <= g) { h.hue = (g-b)/(6*(mx-mn)); }
else if(mx==r && g < b)  { h.hue = (g-b)/(6*(mx-mn))+1; }
else if(mx==g) { h.hue=(b-r)/(6*(mx-mn))+1/3; }
else if(mx==b) { h.hue=(r-g)/(6*(mx-mn))+2/3; }

if(mx==0) { h.saturation=0; }
else { h.saturation=1-mn/mx; }

h.value=mx;
Yukarıda verilen kod yardımı ile herhangi bir renk HSV uzayına dönüştürülebilir. Ancak kullanılan double değişkenler büyük resimler için çok fazla bellek gerektireceğinden burada bir değişikliğe gitmek gerekmektedir. Bu değişiklikte double değerler yerine tamsayı değerler kullanmaktan geçer. H değerinde yapacağımız küçük sayılacak bir hata ile tüm değerleri 0-255 değerleri arasına çekerek burada işlem yapabiliriz. Böylelikle 8 baytlık double değişkenler yerine 1 baytlık char türü değişkenler ile daha az bellek gerektiren bir program yazabiliriz.

Yazılan kodda bir önceki kodda 1/6 (aslında daha sonra 360 ile çarpıldığından 60) olan H çarpanı 255*1/6=43, sonuca eklenen değerler ise 255/3=85 ve 255*2/3=171 olarak yeniden düzenlenmiştir. 0-1 arasında değişen S ve V değerleri ise 255 ile çarpılarak 1 baytlık tamsayıya dönüştürülmüşlerdir. Üretilen sonuçlar bir öncekinden farklı olarak H değeri yeni resmin R kanalında, S değeri yeni resmin G kanalında ve V değeri de yeni resmin B kanalında saklanmıştır. (Bir önceki koddan farklı olarak değerler 0-255 arasında değiştiğinden değerler bir resim üzerinde de saklanabilir.)
byte r=kaynak.pixels[i][j].red;
byte g=kaynak.pixels[i][j].green;
byte b=kaynak.pixels[i][j].blue;
byte mx=max(r,g,b);
byte mn=min(r,g,b);

if(mx==mn) { 
 im.pixels[i][j].red   = 0;
 im.pixels[i][j].green = 0;
 im.pixels[i][j].blue  = mx;
}
else {
       if(mx==r) { im.pixels[i][j].red = 43*(g-b)/(mx-mn); }
       if(mx==g) { im.pixels[i][j].red = 43*(b-r)/(mx-mn)+85; }
       if(mx==b) { im.pixels[i][j].red = 43*(r-g)/(mx-mn)+171; }

im.pixels[i][j].green=255*(mx-mn)/mx;

im.pixels[i][j].blue=mx;
}
Son olarak basit bir uygulama ile bitirelim. HSV uzayı renge bağlı ayrıştırmalarda kolaylık sağladığını söylemiştik. Şimdi buradan yola çıkarak ilkel bir yüz bulma uygulaması gerçekleştirelim. Yapmamız gereken resmi HSV uzayına dönüştürerek H değrinin insan ten rengine yakın tonları arasında olup olmadığını kontrol ederek uygun resmi filtrelemek. HSV dönüşümünden sonra insan ten rengi H 1-30° , S 30-150 arasında bulunduğundan bu aralık dışında kalan değerler 0 yapılarak basit bir yüz bulma uygulaması gerçekleştirilebilir.
yeni = resim_hsv(resim);

for(int i = 0;i < yeni.bminfo.width; i++) {
    for(int j = 0;j < yeni.bminfo.height; j++) {

 if(yeni.pixels[i][j].red < 30 && yeni.pixels[i][j].red > 1 && yeni.pixels[i][j].green < 150 && yeni.pixels[i][j].green > 30) {
            yeni.pixels[i][j].red   = resim.pixels[i][j].red;
            yeni.pixels[i][j].green = resim.pixels[i][j].green;
            yeni.pixels[i][j].blue  = resim.pixels[i][j].blue; }
         else { 
            yeni.pixels[i][j].red=0; 
            yeni.pixels[i][j].green=0;
            yeni.pixels[i][j].blue=0; }
     }
}
Yazılan programın girdi ve çıktıları şu şekilde olacaktır.


Yukarıda program yardımıyla resim üzerinden yüz bölgesi ilkel olarak bulunmuştur. Morfolojik işlemler ile yanlış bulunan küçük bölgeler temizlenerek daha doğru sonuçlar elde edilebilir.

Hiç yorum yok:

Yorum Gönderme

Görüntü işleme ile ilgili yeni yazıları ve bu sitede yer alan yazıların güncellenmiş sürümlerini www.imlab.io veya cescript.github.io adreslerinden takip edebilirsiniz.

X