Estou procurando algum tipo de fórmula ou algoritmo para determinar o brilho de uma cor, considerando os valores RGB. Sei que não pode ser tão simples quanto adicionar valores RGB e somar valores mais altos, mas estou meio que sem saber por onde começar.
387
Respostas:
Você quer dizer brilho? Brilho percebido? Luminância?
(0.2126*R + 0.7152*G + 0.0722*B)
[1](0.299*R + 0.587*G + 0.114*B)
[2]→sqrt( 0.241*R^2 + 0.691*G^2 + 0.068*B^2 )
sqrt( 0.299*R^2 + 0.587*G^2 + 0.114*B^2 )
(graças a @MatthewHerbst ) [3]fonte
0.299*(R^2)
(porque exponenciação vai antes de multiplicação)Eu acho que o que você está procurando é a fórmula de conversão RGB -> Luma .
Fotométrico / digital ITU BT.709 :
ITU digital BT.601 (dá mais peso aos componentes R e B):
Se você deseja trocar precisão por desempenho, há duas fórmulas de aproximação para esta:
Estes podem ser calculados rapidamente como
fonte
Blue
+ 3 * verde) / 6, a segunda é (3 * vermelho +Blue
+ * * verde) >> 3. concedido, em ambas as aproximações rápidas, o azul tem o menor peso, mas ainda está lá.Y = (R<<1+R+G<<2+B)>>3
(são apenas 3-4 ciclos de CPU no ARM), mas acho que um bom compilador fará essa otimização para você.Fiz comparação dos três algoritmos na resposta aceita. Gerei cores em ciclo, onde apenas cerca de 400 cores foram usadas. Cada cor é representada por 2x2 pixels, as cores são classificadas do mais escuro ao mais claro (da esquerda para a direita, de cima para baixo).
1ª foto - Luminância (relativa)
Segunda foto - http://www.w3.org/TR/AERT#color-contrast
Terceira foto - HSP Color Model
4ª foto - WCAG 2.0 SC 1.4.3 fórmula de luminância relativa e taxa de contraste (veja a resposta da @ Synchro aqui )
Às vezes, o padrão pode ser visto na 1ª e 2ª figuras, dependendo do número de cores em uma linha. Eu nunca vi nenhum padrão na imagem do terceiro ou quarto algoritmo.
Se eu tivesse que escolher, eu usaria o algoritmo número 3, já que é muito mais fácil de implementar e é cerca de 33% mais rápido que o quarto.
fonte
^2
esqrt
incluído na terceira fórmula são uma maneira mais rápida de aproximar o RGB linear do RGB não linear em vez do^2.2
e^(1/2.2)
isso seria mais correto. Usar entradas não lineares em vez de lineares é extremamente comum, infelizmente.Abaixo está o único algoritmo CORRETO para converter imagens sRGB, usadas em navegadores etc., em escala de cinza.
É necessário aplicar uma inversa da função gama para o espaço de cores antes de calcular o produto interno. Em seguida, você aplica a função gama ao valor reduzido. A não incorporação da função gama pode resultar em erros de até 20%.
Para coisas típicas do computador, o espaço de cores é sRGB. Os números certos para sRGB são aprox. 0,21, 0,72, 0,07. Gamma para sRGB é uma função composta que aproxima a exponenciação por 1 / (2.2). Aqui está a coisa toda em C ++.
fonte
A resposta "Aceita" está incorreta e incompleta
As únicas respostas precisas são as respostas @ jive-dadson e @EddingtonsMonkey , e no suporte @ nils-pipenbrinck . As outras respostas (incluindo as aceitas) estão vinculando ou citando fontes erradas, irrelevantes, obsoletas ou quebradas.
Resumidamente:
A seguir, uma resposta correta e completa:
Como esse tópico aparece muito nos mecanismos de pesquisa, estou adicionando esta resposta para esclarecer os vários equívocos sobre o assunto.
O brilho é um atributo perceptivo, não possui uma medida direta.
A luminosidade percebida é medida por alguns modelos de visão como CIELAB, aqui L * (Lstar) é uma medida da luminosidade perceptiva e não é linear para aproximar a curva de resposta não linear da visão humana.
A luminância é uma medida linear da luz, ponderada espectralmente para a visão normal, mas não ajustada para a percepção não linear da luminosidade.
Luma ( Y´ prime) é um sinal ponderado e codificado por gama usado em algumas codificações de vídeo. Não deve ser confundido com luminância linear.
A curva gama ou transferência (TRC) é uma curva que geralmente é semelhante à curva perceptiva e é comumente aplicada a dados de imagem para armazenamento ou transmissão, a fim de reduzir o ruído percebido e / ou melhorar a utilização dos dados (e razões relacionadas).
Para determinar a luminosidade percebida , primeiro converta os valores da imagem R´G´B´ codificados por gama em luminância linear (
L
ouY
) e depois em luminosidade percebida não linear (L*
)PARA ENCONTRAR A LUMINÂNCIA:
... Porque aparentemente estava perdido em algum lugar ...
Passo um:
Converta todos os valores inteiros sRGB de 8 bits em decimal 0,0-1,0
Passo dois:
Converta um RGB codificado em gama em um valor linear. O sRGB (padrão do computador), por exemplo, requer uma curva de potência de aproximadamente V ^ 2,2, embora a transformação "precisa" seja:
Onde V 'é o canal R, G ou B codificado por gama de sRGB.
Pseudo-código:
Passo três:
Para encontrar a luminância (Y), aplique os coeficientes padrão para sRGB:
Pseudocódigo usando as funções acima:
PARA ENCONTRAR LEVEZA PERCEBIDA:
Etapa quatro:
Pegue a luminância Y de cima e transforme em L *
Pseudo-código:
L * é um valor de 0 (preto) a 100 (branco), em que 50 é o "cinza do meio" perceptivo. L * = 50 é o equivalente de Y = 18,4, ou seja, um cartão cinza de 18%, representando o meio de uma exposição fotográfica (zona V de Ansel Adams).
Referências:
IEC 61966-2-1:1999 Standard
Wikipedia sRGB
Wikipedia CIELAB
Wikipedia CIEXYZ
Perguntas frequentes sobre a gama de Charles Poynton
fonte
Luma=rgb2gray(RGB);LAB=rgb2lab(RGB);LAB(:,:,2:3)=0;PerceptualGray=lab2rgb(LAB);
L*a*b*
não leva em consideração vários atributos psicofísicos. O efeito Helmholtz-Kohlrausch é um, mas existem muitos outros. O CIELAB não é um modelo de avaliação de imagem "completo" por qualquer meio. No meu post, eu estava tentando cobrir os conceitos básicos da maneira mais completa possível, sem me aventurar nas minúcias muito profundas. O modelo de Hunt, os modelos de Fairchild e outros fazem um trabalho mais completo, mas também são substancialmente mais complexos.Encontrei este código (escrito em C #) que faz um excelente trabalho ao calcular o "brilho" de uma cor. Nesse cenário, o código está tentando determinar se deve colocar texto branco ou preto sobre a cor.
fonte
Curiosamente, esta formulação para RGB => HSV apenas usa v = MAX3 (r, g, b). Em outras palavras, você pode usar o máximo de (r, g, b) como o V no HSV.
Eu verifiquei e, na página 575 da Hearn & Baker, é assim que eles calculam "Valor" também.
fonte
Em vez de se perder na seleção aleatória de fórmulas mencionadas aqui, sugiro que você siga a fórmula recomendada pelos padrões do W3C.
Aqui está uma implementação simples, porém exata, do PHP das fórmulas de luminância relativa e relação de contraste das WCAG 2.0 SC 1.4.3 . Produz valores adequados para avaliar as proporções necessárias para a conformidade com as WCAG, como nesta página , e, como tal, são adequadas e apropriadas para qualquer aplicativo Web. Isso é trivial para portar para outros idiomas.
fonte
Para adicionar o que todos os outros disseram:
Todas essas equações funcionam bem na prática, mas se você precisar ser muito preciso, primeiro você precisa converter a cor em um espaço linear de cores (aplicar imagem-gama inversa), fazer a média ponderada das cores primárias e - se quiser exibir a cor - leve a luminância de volta para a gama do monitor.
A diferença de luminância entre ignorar gama e executar uma gama adequada é de até 20% no cinza escuro.
fonte
Hoje eu estava resolvendo uma tarefa semelhante em javascript. Eu decidi nessa
getPerceivedLightness(rgb)
função para uma cor RGB HEX. Ele lida com o efeito Helmholtz-Kohlrausch via fórmula de Fairchild e Perrotta para correção da luminância.fonte
O espaço de cores HSV deve fazer o truque, consulte o artigo da wikipedia dependendo do idioma em que você está trabalhando, você pode obter uma conversão de biblioteca.
H é matiz, que é um valor numérico para a cor (ou seja, vermelho, verde ...)
S é a saturação da cor, ou seja, quão 'intensa' é
V é o 'brilho' da cor.
fonte
Valor de luminância RGB = 0,3 R + 0,59 G + 0,11 B
http://www.scantips.com/lumin.html
Eu acho que o espaço de cores RGB é perceptivamente não uniforme em relação à distância euclidiana L2. Espaços uniformes incluem CIE LAB e LUV.
fonte
A fórmula gama-inversa de Jive Dadson precisa remover o meio-ajuste quando implementada em Javascript, ou seja, o retorno da função gam_sRGB precisa ser return int (v * 255); não retorna int (v * 255 + 0,5); O meio-ajuste é arredondado para cima, e isso pode causar um valor muito alto em uma tríade R = G = B, ou seja, cinza. A conversão em escala de cinza em uma tríade R = G = B deve produzir um valor igual a R; é uma prova de que a fórmula é válida. Consulte Nove tons de escala de cinza para obter a fórmula em ação (sem o meio ajuste).
fonte
Eu me pergunto como esses coeficientes rgb foram determinados. Eu mesmo fiz um experimento e acabei com o seguinte:
Perto, mas obviamente diferente dos coeficientes ITU estabelecidos há muito tempo. Eu me pergunto se esses coeficientes poderiam ser diferentes para cada observador, porque todos nós podemos ter uma quantidade diferente de cones e hastes na retina em nossos olhos, e especialmente a proporção entre os diferentes tipos de cones pode ser diferente.
Para referência:
ITU BT.709:
ITU BT.601:
Eu fiz o teste movendo rapidamente uma pequena barra cinza em um fundo vermelho brilhante, verde brilhante e azul brilhante e ajustando o cinza até que ele se misturasse o máximo possível. Também repeti esse teste com outros tons. Repeti o teste em telas diferentes, mesmo com um fator gama fixo de 3,0, mas tudo parece o mesmo para mim. Além do mais, os coeficientes da UIT literalmente estão errados aos meus olhos.
E sim, presumivelmente tenho uma visão de cores normal.
fonte
Aqui está um pouco do código C que deve calcular corretamente a luminância percebida.
fonte
Por favor, defina o brilho. Se você está procurando o quão perto da cor branca está, pode usar a Distância Euclidiana de (255, 255, 255)
fonte
O 'V' do HSV é provavelmente o que você está procurando. O MATLAB possui uma função rgb2hsv e o artigo da wikipedia mencionado anteriormente está cheio de pseudocódigo. Se uma conversão RGB2HSV não for viável, um modelo menos preciso seria a versão em escala de cinza da imagem.
fonte
Este link explica tudo em profundidade, incluindo o motivo pelo qual essas constantes multiplicadoras existem antes dos valores R, G e B.
Edit: Tem uma explicação para uma das respostas aqui também (0,299 * R + 0,587 * G + 0,114 * B)
fonte
Para determinar o brilho de uma cor com R, converto a cor do sistema RGB na cor do sistema HSV.
No meu script, eu uso o código do sistema HEX antes por outro motivo, mas você pode iniciar também com o código do sistema RGB com
rgb2hsv {grDevices}
. A documentação está aqui .Aqui está esta parte do meu código:
fonte
Para maior clareza, as fórmulas que usam uma raiz quadrada precisam ser
sqrt(coefficient * (colour_value^2))
não
sqrt((coefficient * colour_value))^2
A prova disso está na conversão de uma tríade R = G = B em R. na escala de cinzas. Isso só será verdade se você quadrado o valor da cor, não o valor da cor vezes o coeficiente. Veja Nove tons de escala de cinza
fonte