() translation by (you can also view the original English article)
Lembra quando você viu aquela imagem de baixa qualidade e se sentiu um pouco decepcionado? Ela não estava clara o suficiente, e os detalhes estavam um pouco confusos. E se você pudesse melhorar essa imagem? Não seria ótimo? Felizmente, existe uma maneira de fazer isso, usando Python!
Dentre os métodos que você pode usar para aumentar a qualidade de uma imagem, um deles é a equalização de histograma, que em particular aumenta o contraste da imagem. Quase todos os sistemas de câmera realmente usam a equalização do histograma para fazer nossas fotos parecerem melhor, e no final do tutorial você vai descobrir por que isso é assim.
Na próxima seção, eu vou me aprofundar em o que se entende por equalização de histograma e o que acontece com a imagem ao aplicar o método, e depois vamos ver como podemos implementar isso em Python. Pronto?
Equalização de Histograma
Digamos que você tenha a imagem pout.jpg (vá em frente e faça o download). Esta é uma imagem de demonstração utilizada no MATLAB, local de onde eu a retirei, mas vamos usá-la em nosso tutorial aqui. A imagem parece da seguinte forma:



Vamos dar uma olhada em como podemos acessar os valores de pixel da imagem, conhecidos como intensidades. Eu escrevi este pequeno script Python que podemos usar para fazer isso (note que estou usando a biblioteca OpenCV):
1 |
import cv2 |
2 |
|
3 |
img = cv2.imread('pout.jpg') |
4 |
img_shape = img.shape |
5 |
height = img_shape[0] |
6 |
width = img_shape[1] |
7 |
|
8 |
for row in range(width): |
9 |
for column in range(height): |
10 |
print (img[column][row]) |
O que estou fazendo aqui é ler a nossa imagem (pout.jpg), e então descobrir o seu formato (tamanho). img_shape
irá retornar: (1031, 850, 3)
. Isso significa que nossa imagem tem altura (número de colunas) 1031
, e largura (número de linhas) 850
- além disso, tem 3
canais (RGB). Observe que o primeiro parâmetro no resultado é a altura, o segundo parâmetro é a largura. Finalmente, podemos percorrer as linhas e colunas e imprimir os diferentes valores de pixel (intensidades) em cada par de linha/coluna.
Uma amostra de saída é: [137 137 137]
. Sim, eu sei, você estava esperando um valor como resultado para a intensidade do pixel. Na verdade, temos o valor da intensidade pixel aqui, mas o que a saída está nos mostrando são os resultados dos canais vermelho, verde e azul (RGB
). Esteja ciente, entretanto, que na OpenCV a ordem é BGR
, já que é assim que a biblioteca carrega a imagem. Dessa forma, o resultado do exemplo acima contém o valor 137
para cada canal, na ordem de B
, G
e R
, respectivamente.
A razão da introdução é que a equalização de histograma se dá através da modificação das intensidades de cada pixel - a fim de melhorar o contraste da imagem. Assim, nosso principal trabalho aqui será o de nivelar a intensidade do pixel.
Neste ponto, você deve estar se perguntando o que um histograma é. Embora às vezes o termo possa parecer um pouco confuso, ele é, na verdade, um conceito muito simples. O histograma é simplesmente um diagrama que representa o número de pixels em uma imagem para cada valor de intensidade encontrado naquela imagem.
Partindo do princípio de que os nossos pixels têm três valores, um para cada um dos canais de BGR, uma maneira de desenhar o histograma é ter três histogramas, um para cada canal, onde o eixo x terá os possíveis valores de cada pixel (intensidades), e o eixo y mostrará quantas vezes (frequência) esse valor de pixel específico apareceu entre todos os valores encontrados.
Por exemplo, o histograma do canal vermelho pode ter um valor de pixel de 137
no eixo x e o eixo y pode mostrar quantos pixels tinha esse valor para o canal vermelho - digamos, 86
. Então, a maneira que lemos esse tipo de gráfico é dizendo que o valor de pixel (no canal vermelho) para intensidade 137
apareceu 86
vezes; ou seja, ele se repetiu 86
vezes em nossa imagem.
Usando o código deste artigo sobre histograma de imagem, podemos desenhar o histograma para a nossa foto. Nós temos, então, o seguinte:



O histograma é, na verdade, para os canais vermelho, verde e azul. Vamos olhar uma pequena amostra da saída que você obteria a partir do código anterior. Isso mostra que os valores do canal parecem ser sempre os mesmo, e as três diferentes linhas desenhadas terão, assim, os mesmos valores e serão, portanto, plotadas uma em cima da outra, aparecendo como se houvesse apenas uma delas.
1 |
[94 94 94]
|
2 |
[95 95 95]
|
3 |
[97 97 97]
|
4 |
[99 99 99]
|
5 |
[100 100 100]
|
6 |
[101 101 101]
|
7 |
[101 101 101]
|
8 |
[101 101 101]
|
9 |
[100 100 100]
|
10 |
[98 98 98]
|
11 |
[95 95 95]
|
12 |
[93 93 93]
|
O que o método de equalização de histograma fará para o histograma acima é transformar os valores de intensidade de tal modo que irá fazer com que o histograma pareça mais plano na imagem resultante. Em outras palavras, a equalização do histograma é um método que ajusta as intensidades da imagem para realçar o contraste dela.
O histograma acima parece um pouco concentrado em direção ao meio da figura, e o que a equalização de histograma vai fazer é distribuir os valores de intensidade dos pixels a fim de obter um histograma mais achatado.
Acho que essa é discussão sobre equalização de histograma que tivemos é suficiente - já que nós não queremos ter mais matemática neste tutorial, especialmente porque esse é um artigo sobre a implementação do método em Python. No entanto, você pode verificar estas notas que mostram as diferentes fórmulas envolvidas no método: equalização de histograma. Agora vamos mergulhar para a implementação.
Equalização de Histograma em Python
Nesta seção, mostrarei como implementar o método de equalização de histograma em Python. Vamos usar a imagem acima (pout.jpg) em nossos experimentos. Vamos rever o processo passo a passo. A primeira coisa que precisamos fazer é importar as bibliotecas OpenCV e NumPy, como mostrado a seguir:
1 |
import cv2 |
2 |
import numpy |
Depois disso, nós simplesmente precisamos ler nossa imagem, pout.jpg:
1 |
img = cv2.imread('pout.jpg') |
A boa notícia é que OpenCV nos fornece uma função através da qual podemos aplicar equalização de histograma em uma imagem - a equalizeHist(). A sua aplicação é simples em uma imagem em tons de cinza, mas no nosso caso, temos três canais (RGB) para cada pixel e não podemos aplicar equalização de histograma em três canais de maneira separada.
Para esse problema, encontrei uma solução no livro Python: Aprendizado de Máquina no Mundo Real, que converte a nossa imagem para o espaço de cor YUV, equaliza o canal Y
e finalmente converte o resultado para RGB. Então a primeira coisa a se fazer é converter a nossa imagem para YUV
. Isso pode ser feito usando o método cvtColor(), que converte a imagem de um espaço de cor para outro, como mostrado a seguir:
1 |
img_to_yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV) |
Observe que usamos BGR
em vez de RGB
aqui, já que o OpenCV (como mencionado antes) carrega as imagens no formato BGR
.
Agora aplicamos o método de equalização de histograma no canal Y,
usando o equalizeHist():
1 |
img_to_yuv[:,:,0] = cv2.equalizeHist(img_to_yuv[:,:,0]) |
Finalmente, podemos converter o canal Y
para RGB
(BGR
no OpenCV), mostrado a seguir:
1 |
hist_equalization_result = cv2.cvtColor(img_to_yuv, cv2.COLOR_YUV2BGR) |
Parabéns! Agora você acabou de aplicar equalização de histograma na imagem. Na próxima subseção, vou juntar todo o código e mostrar-lhe como nossa imagem parecerá após a aplicação de equalização de histograma.
Colocando Tudo Junto
Vamos juntar tudo o que aprendemos. O script Python aplicando a equalização de histograma na pout.jpg
é mostrado a seguir:
1 |
import cv2 |
2 |
import numpy |
3 |
|
4 |
img = cv2.imread('pout.jpg') |
5 |
img_to_yuv = cv2.cvtColor(img,cv2.COLOR_BGR2YUV) |
6 |
img_to_yuv[:,:,0] = cv2.equalizeHist(img_to_yuv[:,:,0]) |
7 |
hist_equalization_result = cv2.cvtColor(img_to_yuv, cv2.COLOR_YUV2BGR) |
8 |
|
9 |
cv2.imwrite('result.jpg',hist_equalization_result) |
A saída do script acima é a imagem a seguir:



Perceba a diferença, vou colocar as duas imagens lado a lado (à esquerda: imagem original; à direita: resultado de equalização de histograma):



Você notou a diferença? A imagem da direita parece muito mais clara do que a imagem original. Não me surpreende o fato de quase todos os sistemas de imagem realizam, de algum modo, a equalização do histograma!
Antes de concluirmos, vamos ver como se parece o histograma do nosso resultado:



Se você comparar o histograma da imagem resultante com o histograma da imagem original, você vai notar que o histograma da imagem resultante é mais plano do que o histograma da imagem original, e isso é exatamente o que faz o método de equalização de histograma.
Conclusão
Neste tutorial, vimos como podemos melhorar o contraste de uma imagem usando um método chamado de equalização de histograma, e como é fácil implementá-lo usando Python e OpenCV.
O resultado foi bem interessante - com uma foto muito mais clara do que a imagem original. E o histograma do resultado foi, como mostrado há pouco, mais "plano" do que o histograma da imagem original, evidenciando uma melhor distribuição dos valores de intensidade de pixel ao longo da imagem.
Finalmente, não hesite em ver o que temos disponível para venda e para seus estudos no Envato Market, e por favor, faça perguntas e dê seu feedback usando a seção abaixo.