RGB'yi gri tonlamaya / yoğunluğa dönüştürme


130

RGB'den gri tonlamaya dönüştürürken, R, G ve B kanallarına belirli ağırlıkların uygulanması gerektiği söylenir. Bu ağırlıklar: 0.2989, 0.5870, 0.1140.

Bunun nedeninin bu üç renge karşı farklı insan algısı / duyarlılığı olduğu söyleniyor. Bazen bunların NTSC sinyalini hesaplamak için kullanılan değerler olduğu da söylenir.

Ancak, bunun için web'de iyi bir referans bulamadım. Bu değerlerin kaynağı nedir?

Ayrıca şu önceki sorulara da bakın: burada ve burada .


26
Evet öyle. Her zaman RGB değerleri üzerinde programlama yapıyorum. Uygulamanızın karşılığını almasını istiyorsanız bu hesaplamalara "gerçek dünya" değerlerini uygulamak çok önemlidir.
Neil N

1
Birçok programcı "yanlış" gri tonlamalı resimleri önemsemeyebilir ve hesaplamayabilir, ama ben umursuyorum.
ypnos

6
Kodlamayla ilgili olduğuna katılıyorum - eğer grafikleri kodluyorsanız meydan okurcasına ilginç ve alakalı bir problem. Cevabı kendim bilmek istediğim için +1
Cruachan

6
RGB , programlama ile ilgilidir. Tarih dizelerini ayrıştırmakla ilgili programlama kadar. "True" metnini bir boole değerine dönüştürürken.
Neil N

Yanıtlar:


87

Sorudaki belirli numaralar CCIR 601'den alınmıştır (aşağıdaki Wikipedia bağlantısına bakın).

RGB -> gri tonlamayı biraz farklı sayılarla / farklı yöntemlerle dönüştürürseniz, normal aydınlatma koşullarında normal bir bilgisayar ekranında pek bir fark görmezsiniz - deneyin.

İşte genel olarak renkle ilgili birkaç bağlantı daha:

Wikipedia Luma

Bruce Lindbloom'un olağanüstü web sitesi

Colin Ware'in "Bilgi Görselleştirme" adlı kitabında Renk üzerine bölüm 4, isbn 1-55860-819-2; books.google.com’daki bu uzun Ware bağlantısı çalışabilir veya çalışmayabilir

cambridgeincolor : mükemmel, iyi yazılmış "prosedüre göre kavramı vurgulayan görsel odaklı bir yaklaşım kullanarak dijital fotoğrafların nasıl elde edileceğine, yorumlanacağına ve işleneceğine dair eğitimler"

"Doğrusal" ve "doğrusal olmayan" RGB ile karşılaşırsanız, işte bu konuda kendime eski bir notun parçası. Tekrar ediyorum, pratikte pek bir fark görmeyeceksiniz.


RGB -> ^ gama -> Y -> L *

Renk biliminde, html rgb'de olduğu gibi (% 10,% 20,% 30) yaygın RGB değerleri "doğrusal olmayan" veya Gama düzeltmeli olarak adlandırılır . "Doğrusal" değerler şu şekilde tanımlanır:

Rlin = R^gamma,  Glin = G^gamma,  Blin = B^gamma

birçok PC için gama 2,2'dir. Normal RGB bazen R 'G' B '(R' = Rlin ^ (1 / gamma)) (sadık dil tıklama) olarak yazılır, ancak burada '.

Bir CRT ekrandaki parlaklık, RGBlin = RGB ^ gama ile orantılıdır, bu nedenle bir CRT'deki% 50 gri oldukça karanlıktır: .5 ^ 2.2 = maksimum parlaklığın% 22'si. (LCD ekranlar daha karmaşıktır; ayrıca bazı grafik kartları gama dengesini sağlar.)

L*RGB'den çağrılan açıklığın ölçüsünü elde etmek için önce RGB'yi 255'e bölün ve hesaplayın

Y = .2126 * R^gamma + .7152 * G^gamma + .0722 * B^gamma

Bu YXYZ renk uzayındadır; renk "parlaklığının" bir ölçüsüdür. (Gerçek formüller tam olarak x ^ gama değildir, ancak birbirine yakındır; ilk geçiş için x ^ gama ile bağlı kalın.)

En sonunda,

L* = 116 * Y ^ 1/3 - 16

"... algısal tekdüzelik arzusu [ve] insanın hafiflik algısıyla yakından eşleşir." - Wikipedia Lab renk alanı


8
Y = 0.2126 * R + 0.7152 * G + 0.0722 * B - Wikipedia ( en.wikipedia.org/wiki/Grayscale )
iamantony


9

Rgb'yi gri tonlamaya dönüştürmek için c'de bazı kodlar var. RGB'den gri tonlamaya dönüştürme için kullanılan gerçek ağırlık, 0.3R + 0.6G + 0.11B'dir. Bu ağırlıklar, onlarla oynayabilmeniz için kesinlikle kritik değildir. Onları 0.25R + 0.5G + 0.25B yaptım. Biraz daha koyu bir görüntü oluşturur.

NOT: Aşağıdaki kod, xRGB 32bit piksel biçimini varsayar

unsigned int *pntrBWImage=(unsigned int*)..data pointer..;  //assumes 4*width*height bytes with 32 bits i.e. 4 bytes per pixel
unsigned int fourBytes;
        unsigned char r,g,b;
        for (int index=0;index<width*height;index++)
        {
            fourBytes=pntrBWImage[index];//caches 4 bytes at a time
            r=(fourBytes>>16);
            g=(fourBytes>>8);
            b=fourBytes;

            I_Out[index] = (r >>2)+ (g>>1) + (b>>2); //This runs in 0.00065s on my pc and produces slightly darker results
            //I_Out[index]=((unsigned int)(r+g+b))/3;     //This runs in 0.0011s on my pc and produces a pure average
        }

2
0.3 0.6 0.11 1'e ekleme yok. Wikipedia, 0.30 0.59 0.11 öneriyor gibi görünüyor.
damix911

Doğru, ancak bunların 1'e eklenmemesinin tek sonucu yoğunlukta çok küçük bir değişiklik olacaktır. Önerilen 0,25,0,5,0,25 yöntemi 1'e eklenir, ancak olmasaydı önemli olmazdı. Bu bir optimizasyon olduğundan, küçük bir doğruluk oranından vazgeçmek makul bir değiş tokuş.
Twerdster

2
@twerdster Katsayıların hiçbiri doğru değil. .3, .6, .11 eski NTSC standardıdır, sRGB / Rec709 değil (web ve çoğu bilgisayarın kullandığı şey budur). Ve 0.25.0.5.0.25'iniz makul bir değiş tokuş değil - B parlaklığın yalnızca% 7'si,% 347 kadar yanılıyorsunuz. SRGB / r709 için katsayılar (doğrusallaştırmadan sonra): Rlin * 0.2126 + Glin * 0.7152 + Blin * 0.0722 = Y Bu spektral ağırlıklar insan spektral algısından türetilmiştir. Kolaylık sağlamak için istediğiniz sayıları sıkıştırıp doğru olmayı umamazsınız. SRGB'yi doğrusallaştırmanız ve ardından doğru katsayıları uygulamanız gerekir.
Myndex

Eğer bölmek çok pahalı bir durumda ise, vardiya ile tek çarpma kullanır ve ekler yaklaşık bir değerdir: 0.11111111 * ((G + (G<<1) + R) <<1) + B). Bu (2*R+6*G+B) / 9)veya eşdeğerdir 0.222 R + 0.666 G + 0.111 B. Üretime geçmeden önce, çeşitli test durumları için doğru bir formülle karşılaştırın.
ToolmakerSteve


6

Bununla ilgili bilgi için Renk SSS bölümüne bakın. Bu değerler, ekranlarımızda kullandığımız RGB değerlerinin standardizasyonundan gelir. Aslında, Color FAQ'ye göre, kullandığınız değerler modern monitörler değil orijinal NTSC standardı için kullanılan değerler oldukları için güncelliğini yitirmiş durumda.


3

Bu değerlerin kaynağı nedir?

Gönderilen katsayıların "kaynağı", Rec601 ve Televizyonun Özellikleri'nde görülebilen NTSC spesifikasyonlarıdır .

"Nihai kaynak", insan renk algısı üzerine 1931 dolaylarında CIE deneyleridir. İnsan görüşünün spektral tepkisi tek tip değildir. Deneyler, algıya dayalı olarak tristimulus değerlerinin ağırlıklandırılmasına yol açtı. L, M ve S konilerimiz ( 1 ), tristimulus ana renklerinin türetildiği "Kırmızı", "Yeşil" ve "Mavi" (sırasıyla) olarak tanımladığımız ışık dalga boylarına duyarlıdır. 2

SRGB (ve Rec709) için doğrusal ışık 3 spektral ağırlıkları şunlardır:

R lin * 0.2126 + G lin * 0.7152 + B lin * 0.0722 = Y

Bunlar, bilgisayar monitörlerini (sRGB) veya HDTV monitörlerini (Rec709) temsil etmesi amaçlanan sRGB ve Rec709 renk uzaylarına özgüdür ve Rec709 ve ayrıca BT.2380-2 (10/2018) için ITU belgelerinde ayrıntılı olarak verilmiştir.

DİPNOTLAR (1) Koniler, gözün retinasının renk tespit hücreleridir.
(2) Bununla birlikte, seçilen tristimulus dalga boyları, her bir koni tipinin "zirvesinde" DEĞİLDİR - bunun yerine, tristimulus değerleri, belirli bir koni tipi üzerinde önemli ölçüde diğerinden daha fazla uyaracak şekilde seçilir, yani uyaranın ayrılması.
(3) Katsayıları uygulamadan önce sRGB değerlerinizi doğrusallaştırmanız gerekir. Bunu burada başka bir cevapta tartışıyorum .


-2

Bu değerler, özellikle renk körü kişiler için kişiden kişiye değişir.


-4

tüm bunlar gerçekten gerekli mi, insan algısı ve CRT ile LCD arasında değişiklik olacak, ancak RGB yoğunluğu değişmiyor, Neden L = (R + G + B)/3yeni RGB'yi L, L, L'ye ayarlamıyor?


3
Basitçe üç R, G, B primerlerinin ortalamasını almak, onlara algısal olarak eşit muamele eder, bu insan görme sistemi için geçerli değildir.
Bill Feth
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.