Convertendo RGB em escala de cinza / intensidade


129

Ao converter de RGB para escala de cinza, diz-se que pesos específicos para os canais R, G e B devem ser aplicados. Esses pesos são: 0,2989, 0,5870, 0,1140.

Diz-se que a razão para isso é a percepção / sensibilidade humana diferente em relação a essas três cores. Às vezes, também é dito que esses são os valores usados ​​para calcular o sinal NTSC.

No entanto, não encontrei uma boa referência para isso na web. Qual é a fonte desses valores?

Veja também estas perguntas anteriores: aqui e aqui .


26
Sim. Eu faço programação em valores RGB o tempo todo. A aplicação de valores do "mundo real" a esses cálculos é muito importante se você deseja que seu aplicativo valha a pena.
305 Neil N

1
Muitos programadores podem não se importar e calcular imagens "erradas" em escala de cinza, mas eu sim.
ypnos 26/03/09

6
Eu concordo que está relacionado à codificação - desafiadoramente um problema interessante e relevante se você estiver codificando gráficos. +1 como eu gostaria de saber a resposta
Cruachan

6
RGB está relacionado à programação. É tão relacionado à programação quanto analisar as seqüências de datas. Como converter o texto "true" em um valor booleano.
305 Neil N

Respostas:


87

Os números específicos na pergunta são do CCIR 601 (consulte o link da Wikipedia abaixo).

Se você converter RGB -> escala de cinza com números ligeiramente diferentes / métodos diferentes, não verá muita diferença na tela normal do computador em condições normais de iluminação - experimente.

Aqui estão mais alguns links sobre cores em geral:

Wikipedia Luma

O excelente site de Bruce Lindbloom

o capítulo 4 sobre Cor no livro de Colin Ware, "Visualização da Informação", isbn 1-55860-819-2; esse longo link para o Ware em books.google.com pode ou não funcionar

cambridgeincolor : "tutoriais excelentes e bem escritos sobre como adquirir, interpretar e processar fotografias digitais usando uma abordagem visualmente orientada que enfatiza o conceito sobre o procedimento"

Se você se deparar com RGB "linear" vs "não linear", aqui está parte de uma observação antiga sobre isso. Repita, na prática você não verá muita diferença.


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

Na ciência das cores, os valores comuns de RGB, como em html rgb (10%, 20%, 30%), são chamados de "não lineares" ou corrigidos por gama . Os valores "lineares" são definidos como

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

onde gama é 2.2 para muitos PCs. O RGB usual às vezes é escrito como R 'G' B '(R' = Rlin ^ (1 / gama)) (puristas, clique na língua), mas aqui eu vou largar o '.

O brilho em uma tela CRT é proporcional a RGBlin = RGB ^ gama, portanto 50% de cinza em um CRT é bastante escuro: 0,5 ^ 2,2 = 22% do brilho máximo. (Os monitores LCD são mais complexos; além disso, algumas placas gráficas compensam a gama).

Para obter a medida da luminosidade chamada L*de RGB, primeiro divida o RGB por 255 e calcule

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

Isso está Yno espaço de cores XYZ; é uma medida da cor "luminância". (As fórmulas reais não são exatamente x ^ gama, mas fecham; use x ^ gama para uma primeira passagem.)

Finalmente,

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

"... aspira à uniformidade perceptiva [e] se aproxima da percepção humana da leveza." - Espaço de cores do Wikipedia Lab


8
Y = 0,2126 * R + 0,7152 * G + 0,0722 * B - Wikipedia ( en.wikipedia.org/wiki/Grayscale )
iamantony


9

Heres algum código em c para converter rgb em escala de cinza. O peso real usado para conversão de rgb em escala de cinza é 0.3R + 0.6G + 0.11B. esses pesos não são absolutamente críticos para que você possa brincar com eles. Eu os fiz 0.25R + 0.5G + 0.25B. Produz uma imagem um pouco mais escura.

NOTA: O código a seguir assume o formato de pixel xRGB de 32 bits

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 não adiciona a 1. Wikipedia parece sugerir 0,30 0,59 0,11.
damix911

É verdade, mas o único resultado de não adicionar 1 será uma mudança muito leve na intensidade. O método proposto de 0,25,0,5,0,25 aumenta para 1, mas não importa se não. É uma otimização, portanto, abrir mão de um pouquinho de precisão é uma troca razoável.
Twerdster 13/10

2
@twerdster Nenhum conjunto de coeficientes está correto. .3, .6, .11 é o antigo padrão NTSC, não o sRGB / Rec709 (que é o que a web e a maioria dos computadores usam). E seu 0.25,0.5,0,25 não é uma troca razoável - B é apenas 7% da luminância, você está 347% errado. Os coeficientes para sRGB / r709 (após linearização): Rlin * 0,2126 + Glin * 0,7152 + Blin * 0,0722 = Y Essas ponderações espectrais são derivadas da percepção espectral humana. Você não pode simplesmente digitar os números desejados por conveniência e espera ser preciso. Você precisa linearizar o sRGB e aplicar os coeficientes corretos.
Myndex 20/05/19

Se você estiver em uma situação onde divisão é muito caro, uma aproximação que utiliza um único multiplicam com as mudanças e adiciona é: 0.11111111 * ((G + (G<<1) + R) <<1) + B). Isso é equivalente a (2*R+6*G+B) / 9)ou 0.222 R + 0.666 G + 0.111 B. Antes de iniciar a produção, compare com uma fórmula precisa para vários casos de teste.
Home


6

Consulte as Perguntas frequentes sobre cores para obter informações sobre isso. Esses valores vêm da padronização dos valores RGB que usamos em nossos displays. Na verdade, de acordo com as Perguntas frequentes sobre cores, os valores que você está usando estão desatualizados, pois são os valores usados ​​para o padrão NTSC original e não para os monitores modernos.


3

Qual é a fonte desses valores?

A "fonte" dos coeficientes publicados são as especificações NTSC que podem ser vistas no Rec601 e Características da televisão .

A "fonte final" são os experimentos da CIE, por volta de 1931, sobre a percepção da cor humana. A resposta espectral da visão humana não é uniforme. Experimentos levaram à ponderação dos valores de tristímulos com base na percepção. Nossos cones L, M e S 1 são sensíveis aos comprimentos de onda da luz que identificamos como "Vermelho", "Verde" e "Azul" (respectivamente), que é onde as cores primárias dos tristímulos são derivadas. 2

As ponderações espectrais da luz linear 3 para sRGB (e Rec709) são:

R lin * 0,2126 + G lin * 0,7152 + B lin * 0,0722 = Y

Eles são específicos para os espaços de cores sRGB e Rec709, destinados a representar monitores de computador (sRGB) ou HDTV (Rec709), e são detalhados nos documentos da UIT para Rec709 e também BT.2380-2 (10/2018)

NOTAS (1) Os cones são as células de detecção de cor da retina do olho.
(2) No entanto, os comprimentos de onda de tristímulo escolhidos NÃO estão no "pico" de cada tipo de cone - em vez disso, os valores de tristímulo são escolhidos de modo a estimular um tipo de cone específico substancialmente mais do que outro, ou seja, separação de estímulos.
(3) Você precisa linearizar seus valores de sRGB antes de aplicar os coeficientes. Discuto isso em outra resposta aqui.


-2

Esses valores variam de pessoa para pessoa, especialmente para pessoas que são daltônicas.


-4

é tudo isso realmente necessário, a percepção humana e o CRT vs LCD variam, mas a intensidade do RGB não. Por que não L = (R + G + B)/3e defina o novo RGB como L, L, L?


3
Simplesmente calcular a média das três primárias R, G, B as trata como perceptualmente iguais, o que não é o caso do sistema de visão humana.
Bill Feth
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.