İnsanların sağladığı referans bağlantıları iyi ve bu soruna birçok çözüm var, ama bu problem üzerinde yakın zamanda çalıştığım için (başkalarının nasıl çözdüğüne dair tam bir cehaletle), yaklaşımımı sunarım Düz İngilizce:
Öncelikle (insan algılanan) rengin 3 boyutlu olduğunu anlayın. Bu temel olarak insan gözünün 3 farklı reseptörü olduğu için: kırmızı, yeşil ve mavi. Aynı şekilde monitörünüzün kırmızı, yeşil ve mavi piksel elemanları vardır. Ton, doygunluk, parlaklık (HSL) gibi diğer gösterimler kullanılabilir, ancak temel olarak tüm sunumlar 3 boyutludur.
Bu, RGB renk uzayının kırmızı, yeşil ve mavi eksenli bir küp olduğu anlamına gelir. 24 bitlik bir kaynak görüntüden, bu küpün her bir eksende 256 ayrık seviyesi vardır. Görüntüyü 8-bit'e indirgemeye yönelik naif bir yaklaşım, sadece eksen başına seviyeyi azaltmaktır. Örneğin, kırmızı ve yeşil için 8 seviyeli 8x8x4 küp paleti, kırmızı ve yeşil değerlerin yüksek 3 bitini ve mavi değerin yüksek 2 bitini alarak 4 seviyeli mavi için kolayca yaratılır. Bu uygulanması kolaydır, ancak bazı dezavantajları vardır. Elde edilen 256 renk paletinde, pek çok giriş kullanılmayacak. Görüntünün çok ince renk değişimlerini kullanarak ayrıntıları varsa, renkler aynı palet girişine eklendikçe bu kaymalar kaybolacaktır.
Uyarlamalı bir palet yaklaşımı, görüntüdeki yalnızca ortalama/ortak renkleri değil, aynı zamanda hangi renk alanı alanlarının en büyük varyansa sahip olduğunu da hesaba katmalıdır.Yani, açık yeşilin binlerce ince tonuna sahip bir görüntü, tam olarak aynı açık yeşil tonda binlerce piksele sahip bir görüntüden farklı bir palet gerektirir; çünkü bu, bu renk için ideal olarak tek bir palet girdisini kullanır.
Bu amaçla, her biri aynı sayıda farklı değer içeren 256 paket içeren bir yaklaşımla karşılaştım. Eğer orijinal görüntü 256000 farklı 24 bit renk içeriyorsa, bu algoritma her biri 1000 orijinal değer içeren 256 kovaya neden olur. Bu, mevcut olan farklı değerlerin medyanını (ortalama değil) kullanarak renk uzayının ikili uzaysal bölümlenmesi ile gerçekleştirilir.
Türkçe, bu, tüm renk küpünü ilk olarak, medyan kırmızı değerden daha az olan ve yarının ortanca kırmızı değerinden daha fazla olan piksellerin yarısına bölünmesi anlamına gelir. Ardından, oluşan her bir yarıyı yeşil değere, sonra maviye ve benzeri şekilde bölün. Her bölme, piksellerin alt veya üst yarısını belirtmek için tek bir bit gerektirir. 8 bölmeden sonra, varyans etkin bir şekilde renk uzayında 256 eşit derecede önemli kümeye ayrılmıştır. psuedo kodunda
:
// count distinct 24-bit colors from the source image
// to minimize resources, an array of arrays is used
paletteRoot = {colors: [ [color0,count],[color1,count], ...]} // root node has all values
for (i=0; i<8; i++) {
colorPlane = i%3 // red,green,blue,red,green,blue,red,green
nodes = leafNodes(paletteRoot) // on first pass, this is just the root itself
for (node in nodes) {
node.colors.sort(colorPlane) // sort by red, green, or blue
node.lo = { colors: node.colors[0..node.colors.length/2] }
node.hi = { colors: node.colors[node.colors.length/2..node.colors.length] }
delete node.colors // free up space! otherwise will explode memory
node.splitColor = node.hi.colors[0] // remember the median color used to partition
node.colorPlane = colorPlane // remember which color this node split on
}
}
Artık renk küpünde mekansal kümelenmiş 256 yaprak düğümleri, orijinal görüntüden farklı renklerin aynı sayıda içeren her vardır. Her bir düğüme tek bir renk atamak için, renk sayılarını kullanarak ağırlıklı ortalamayı bulun. Ağırlık, algısal renk eşleştirmesini geliştiren bir optimizasyondur, ancak bu önemli değildir. Her bir renk kanalını bağımsız olarak ortalama yaptığınızdan emin olun. Sonuçlar mükemmel. Gözdeki mavi reseptörlerin kırmızı ve yeşilden daha az hassas değişikliklere daha az duyarlı olduğu için, mavinin kırmızı ve yeşilden daha az bir kez ayrıldığına dikkat edilmelidir.
Başka optimizasyonlar da mümkündür. HSL'yi kullanarak daha yüksek niceleme değerini mavi yerine parlaklık boyutuna koyabilirsiniz. Ayrıca, yukarıdaki algoritma genel dinamik aralığını biraz azaltacaktır (sonuçta renk değerlerini ortalama olarak aldığından), sonuçta ortaya çıkan paleti dinamik olarak genişletmek başka bir olasılıktır.
Bu basit bir işlem değildir. Bu tür bir dönüşüme girebilecek çok şey var (örneğin, dithering ve insan renk algısı). Sen sadece bir ağız dolusu ... tam bir üniversite dersi dolu, iyi bir soru için iyi bir soru için ... – JoshD
+1 bahsettim ... cevabımı aşağıya bakın. 24 bit değerler ve standart "web güvenli" palet arasında dönüştürme ile başlamak isteyebilirsiniz. Bu, kendi paletinizi belirlemekten çok daha az karmaşık olacaktır (muhtemelen çok da eğlenceli değil). –