Opencv advanced 01-aplicativo e exemplo de histograma cv2.calcHist()

O que é um histograma?

Um histograma é uma representação gráfica usada para mostrar a distribuição de valores individuais ou faixas de valores em dados. Ele divide os dados em uma série de intervalos (também conhecidos como "bins" ou "bins") e, em seguida, conta a frequência (ou frequência) dos dados em cada intervalo. Os histogramas podem nos ajudar a entender melhor as características de distribuição dos dados, incluindo tendência central, dispersão, etc.

Os principais recursos dos histogramas incluem:

1. Eixo horizontal (eixo X) : O eixo horizontal representa a faixa numérica ou intervalo dos dados. Cada intervalo é normalmente representado por dois valores numéricos, por exemplo, 0-10, 10-20, etc.

2. Eixo vertical (eixo Y ): O eixo vertical representa a frequência (ou frequência) dos dados em cada intervalo, ou seja, o número de vezes que os dados aparecem nesse intervalo.

3. Gráfico de barras : O gráfico do histograma é composto por uma série de barras retangulares, a largura de cada barra retangular representa a largura do intervalo e a altura representa a frequência dos dados no intervalo.

4. Dados contínuos : 直方图适用于连续型数据, como dados de medição, dados de tempo, etc. 对于离散型数据,柱状图可能更为适合.

Os histogramas têm aplicações importantes em muitos campos, incluindo estatística, processamento de imagem, análise de dados, etc. No processamento de imagem, o histograma pode ser usado para analisar a distribuição de valor de pixel da imagem, de modo a realizar aprimoramento de imagem, ajuste de contraste, segmentação de imagem e outras operações. Nas estatísticas, os histogramas podem nos ajudar a entender a distribuição dos dados, como distribuição normal, distribuição assimétrica, etc. Ao observar o histograma, podemos ter uma compreensão mais profunda das características dos dados, de modo a tomar decisões e análises mais precisas

Significado do histograma na imagem

Do ponto de vista estatístico, o histograma é uma função entre as características estatísticas do valor de cinza da imagem e o valor de cinza da imagem, e o histograma conta o número de ocorrências de cada nível de cinza na imagem.从直方图的图形上观察,横坐标是图像中各像素点的灰度级,纵坐标是具有该灰度级(像素值)的像素个数。

Por exemplo, considere a imagem mostrada na Figura 13-1. Existem apenas 9 pixels nesta imagem e 1, 2, 3, 4, 5, um total de 5 níveis de cinza.

insira a descrição da imagem aqui

Conte o número de ocorrências de cada nível de cinza, conforme mostrado na Tabela 13-1

insira a descrição da imagem aqui
Ao desenhar um histograma, o nível de cinza é tratado como o eixo x, e o número de ocorrências do nível de cinza é tratado como o eixo y, então pode-se saber que:

  • Os dados do eixo x são x=[1 2 3 4 5].
  • Os dados do eixo y são y=[3 1 2 1 2].

De acordo com a relação acima, o gráfico de linhas (imagem à esquerda) e o histograma (imagem à direita) conforme mostrado na Figura 13-2 podem ser desenhados. Em geral, nos referimos ao gráfico de linha reta à esquerda e ao histograma à direita como histogramas.

insira a descrição da imagem aqui

No processamento real, o intervalo do eixo x do histograma da imagem é geralmente [0, 255], correspondendo aos 256 níveis de cinza do bitmap de 8 bits; o eixo y corresponde ao número de pixels com níveis de cinza correspondentes.

Por exemplo, na Figura 13-3, a imagem superior é uma imagem e a imagem inferior é seu histograma correspondente. Os pontos na figura indicam que esses pixels serão contados no nível de cinza correspondente.

insira a descrição da imagem aqui

Embora todas as imagens de 8 bits tenham 256 níveis de cinza (cada pixel pode ter 256 valores de cinza), o número de pixels pertencentes a diferentes níveis de cinza é muito diferente.

Por exemplo, na Figura 13-4, pode-se ver na figura que os histogramas de diferentes partes da imagem são diferentes.
insira a descrição da imagem aqui

Às vezes, um histograma normalizado também é usado para facilitar a apresentação. No histograma normalizado, o eixo x ainda representa níveis de cinza; o eixo y não representa mais o número de ocorrências de níveis de cinza, mas a frequência de ocorrências de níveis de cinza.
Por exemplo, para a Figura 13-1, a frequência de ocorrência de cada nível de cinza é contada:

A frequência de ocorrências em tons de cinza = o número de ocorrências em tons de cinza/número total de pixels

Existem 9 pixels na Figura 13-1, então os resultados estatísticos são mostrados na Tabela 13-2.

insira a descrição da imagem aqui

No histograma normalizado, a soma da frequência de cada nível de cinza é 1. Por exemplo, neste caso:

insira a descrição da imagem aqui
Ao desenhar um histograma, trate o nível de cinza como os dados do eixo x e a frequência de sua ocorrência como os dados do eixo y, então podemos saber:

  • Os dados do eixo x são x=[1 2 3 4 5]
  • Os dados do eixo y são y=[3/9 1/9 2/9 1/9 2/9]

De acordo com a relação acima, o histograma normalizado mostrado na Figura 13-5 pode ser desenhado. Comparando a Figura 13-4 e a Figura 13-5, podemos ver que o histograma normalizado e o histograma são consistentes na aparência, mas os rótulos do eixo y são diferentes.

Neste exemplo, no histograma, os rótulos exibidos no eixo y são 1, 2, 3; no histograma normalizado, os rótulos exibidos no eixo y são 1/9, 2/9, 3/9.

insira a descrição da imagem aqui
No site oficial do OpenCV, existem três conceitos que devem ser observados: DIMS, BINS e RANGE.

  • DIMS: Indica o número de parâmetros coletados ao desenhar o histograma. Em geral, há apenas um tipo de dado coletado no histograma, que é o nível de cinza. Portanto, o valor é 1.
  • RANGE: Indica a faixa de tons de cinza a ser contada, geralmente [0, 255]. 0 corresponde ao preto e 255 corresponde ao branco.
  • BINS: Número de subconjuntos de parâmetros. No processo de processamento de dados, às vezes é necessário dividir um grande número de dados em vários grupos para análise.

Por exemplo, para os níveis de cinza na Figura 13-1, você pode querer falar sobre dois valores de pixel como um conjunto. Desta forma, toda a escala de cinza é dividida em três grupos, especificamente { {1,2} , {3,4} , {5} }. A Figura 13-6 mostra o histograma antes e depois da divisão.

insira a descrição da imagem aqui

As imagens em tons de cinza também podem ser divididas da maneira descrita acima. Por exemplo, em uma imagem em tons de cinza, os 256 níveis de tons de cinza no intervalo [0, 255] são divididos em subconjuntos de acordo com cada grupo de 16 pixels:

[0, 255] = [0, 15] ∪ [16, 31] ∪…∪[240, 255]

De acordo com o método acima, toda a faixa de escala de cinza pode ser dividida em 16 subconjuntos, especificamente:

Faixa inteira de escala de cinza = bin1 ∪ bin2 ∪…∪ bin16

Depois que os subconjuntos são divididos, o histograma gerado por uma imagem em tons de cinza é mostrado na Figura 13-7 (b1 na figura representa bin1, b2 representa bin2 e assim por diante).

insira a descrição da imagem aqui
Os valores BINS são discutidos abaixo:

  • Para a Figura 13-1, existem 5 níveis de cinza na imagem original e seu valor BINS é 5. Após subconjunto de um grupo com 2 níveis de cinza, são obtidos 3 subconjuntos, cujo valor BINS é 3.
  • Para a imagem em tons de cinza, o intervalo de tons de cinza é [0, 255], há 256 tons de cinza no total e seu valor BINS é 256; após subconjunto com 16 tons de cinza como um grupo, seu valor BINS é 16.

Para ser franco, é o número de colunas

desenhar histograma

Python 的模块 matplotlib.pyplot 中的 hist()A função pode desenhar facilmente o histograma e geralmente usamos essa função para desenhar o histograma diretamente (isso também é usado no aprendizado de máquina). Além disso, o OpenCV cv2.calcHist()函数pode calcular histogramas estatísticos e também
desenhar histogramas de imagem com base nisso. Esses dois métodos são discutidos separadamente abaixo.

Desenhar histograma usando Numpy

O módulo matplotlib.pyplot fornece uma estrutura semelhante ao método de desenho do MATLAB, que pode ser usado matplotlib.pyplot.hist()函数(daqui em diante chamado de função hist()) para desenhar histogramas.

A função desta função é desenhar um histograma de acordo com a fonte de dados e o agrupamento de níveis de cinza. Seu formato de sintaxe básico é:

matplotlib.pyplot.hist(X, BINS)

Os significados dos dois parâmetros são os seguintes:

  • X: Fonte de dados, deve ser unidimensional. As imagens geralmente são bidimensionais e você precisa usar a função ravel() para processar a imagem em uma fonte de dados unidimensional antes de usá-la como parâmetro.

  • BINS: O valor específico de BINS, indicando o agrupamento de níveis de cinza .

A função de ravel() é reduzir a dimensão de um array bidimensional em um array unidimensional. Por exemplo, existe a imagem a com o valor:

insira a descrição da imagem aqui
Use a função ravel() para processar:

b = a.ravel()

b pode ser obtido como:
insira a descrição da imagem aqui

Exemplo: Use a função hist() para desenhar um histograma de uma imagem.

insira a descrição da imagem aqui
código mostra como abaixo:

import cv2
import matplotlib.pyplot as plt
o=cv2.imread("boat.jpg")
plt.hist(o.ravel(),256)
plt.show()

resultado da operação:

insira a descrição da imagem aqui

Exemplo: Após utilizar a função hist() para dividir o nível de cinza de uma imagem em 16 grupos, desenhe o histograma da imagem.

Altere os 255 acima para 16

import cv2
import matplotlib.pyplot as plt
o=cv2.imread("boat.jpg")
plt.hist(o.ravel(),16)
plt.show()

insira a descrição da imagem aqui

Desenhe um histograma usando o OpenCV

O OpenCV fornece a função cv2.calcHist() para calcular o histograma estatístico da imagem, que pode contar o número de pixels em cada nível de cinza. Usando a função plot() no módulo matplotlib.pyplot, os resultados estatísticos da função cv2.calcHist() podem ser desenhados em um histograma

1. Use a função cv2.calcHist() para contar as informações do histograma da imagem
A função cv2.calcHist() é usada para contar as informações do histograma da imagem, e seu formato de sintaxe é:

hist = cv2.calcHist( images, channels, mask, histSize, ranges, accumulate )

Os significados do valor de retorno e parâmetros na função são:

  • hist: O histograma estatístico retornado é uma matriz unidimensional e os elementos na matriz são o número de pixels em cada nível de cinza.

  • imagens: Imagens originais, que precisam ser colocadas entre "[ ]".

  • canais: especifica o número do canal. O número do canal precisa ser delimitado por "[ ]". Se a imagem de entrada for uma imagem em tons de cinza de canal único, o valor desse parâmetro é [0]. Para imagens coloridas, seus valores podem ser [0], [1], [2], correspondendo aos canais B, G, R, respectivamente.

  • máscara: imagem da máscara. Ao contar o histograma da imagem inteira, defina este valor como Nenhum. Ao contar o histograma de uma determinada parte da imagem, é necessária uma imagem de máscara.

  • histSize: O valor de BINS, que precisa ser colocado entre "[ ]". Por exemplo, o valor de BINS é 256, você precisa usar "[256]" como este valor de parâmetro.

  • intervalos: o intervalo de valores de pixel. Por exemplo, uma imagem em tons de cinza de 8 bits possui valores de pixel no intervalo [0, 255].

  • acumule: sinalizador cumulativo (cumulativo, sobreposto), o valor padrão é Falso. Se for definido como True, o histograma não será apagado no início do cálculo e o cálculo é o resultado cumulativo de vários histogramas, que é usado para calcular o histograma para um grupo de imagens
    . Este parâmetro permite calcular um único histograma de vários objetos ou atualizar o histograma em tempo real. Este parâmetro é opcional e geralmente não precisa ser definido.

Exemplo: Use a função cv2.calcHist() para calcular o resultado do histograma estatístico de uma imagem e observe as informações do histograma estatístico obtidas.

código mostra como abaixo:


import cv2
img=cv2.imread("boat.jpg")
hist = cv2.calcHist([img],[0],None,[16],[0,255])
print(type(hist))
print(hist.shape)
print(hist.size)
print(hist)

Os resultados da execução são os seguintes:
Observe que na função cv2.calcHist() neste exemplo:

  • O primeiro parâmetro "[img]" indica a imagem original para desenhar o histograma, entre "[ ]".
  • O segundo parâmetro indica qual informação do histograma do canal deve ser contada. A img lida neste exemplo é uma imagem em tons de cinza, portanto é
    representada por "[0]".
  • O terceiro parâmetro é a imagem da máscara, neste caso o valor é "None", que significa calcular o histograma de toda a imagem.
  • O quarto parâmetro "[16]" indica que o valor de BINS é 16, ou seja, está dividido em 16 grupos
  • O quinto parâmetro “[0, 255]” indica que a faixa da escala de cinza é [0, 255].
<class 'numpy.ndarray'>
(16, 1)
16
[[ 12575.]
 [ 39591.]
 [ 56651.]
 [ 38932.]
 [ 29997.]
 [ 33472.]
 [ 46033.]
 [ 74555.]
 [199718.]
 [288966.]
 [136663.]
 [ 44440.]
 [ 20355.]
 [ 20691.]
 [  5578.]
 [   344.]]

Exemplo: Desenhe um Histograma Estatístico

import cv2
from matplotlib import pyplot as plt

img=cv2.imread("boat.jpg")
hist = cv2.calcHist([img],[0],None,[16],[0,255])


plt.plot(hist,color='b')
plt.show()

resultado da operação:
insira a descrição da imagem aqui

Todas as funções acima são para exibir imagens em histogramas. Vamos falar sobre as funções de aplicação de histogramas no processamento de imagens.

Equalização do histograma

Se uma imagem tiver todos os níveis de cinza possíveis e os níveis de cinza dos valores de pixel forem distribuídos uniformemente, a imagem terá alto contraste e tons de cinza variáveis, níveis de cinza ricos e grande cobertura. Na aparência, essas imagens têm cores mais ricas e não são excessivamente escuras ou brilhantes.

A Figura 13-22 mostra a comparação de uma imagem antes e depois da equalização do histograma. A imagem da esquerda é a imagem original, que é relativamente escura, a imagem da direita é a imagem após a equalização e a cor é relativamente equilibrada.

insira a descrição da imagem aqui

No site oficial do OpenCV, os histogramas antes e depois da equalização da imagem (ou seja, equalização do histograma) são comparados, conforme mostrado na Figura 13-23. Entre eles, a imagem da esquerda é o histograma da imagem original. Pode-se ver que o nível de cinza está concentrado no meio, e não há pixels mais escuros e claros na imagem; a imagem da direita é o histograma após igualar o original imagem, e a distribuição de pixels é mais equilibrada.

insira a descrição da imagem aqui

O principal objetivo da equalização do histograma é mapear uniformemente o nível de cinza da imagem original para toda a faixa de nível de cinza e obter uma imagem com distribuição uniforme de nível de cinza. Essa equalização não apenas realiza o equilíbrio de probabilidade nas estatísticas de valor cinza, mas também realiza o equilíbrio visual no Sistema Visual Humano (HVS).

Função de equalização de histograma

OpenCV 使用函数 cv2.equalizeHist()实现直方图均衡化. A sintaxe desta função é:

dst = cv2.equalizeHist( src )

Na fórmula:

  • dst é o resultado do processo de equalização do histograma.
  • src é uma imagem bruta de canal único de 8 bits.

Exemplo: Use a função cv2.equalizeHist() para implementar a equalização do histograma.

Imagem original:
insira a descrição da imagem aqui
o código é o seguinte:

#-----------导入使用的模块---------------
import cv2
import matplotlib.pyplot as plt
#-----------读取原始图像---------------
img = cv2.imread('equ.bmp',cv2.IMREAD_GRAYSCALE)
#-----------直方图均衡化处理---------------
equ = cv2.equalizeHist(img)
#-----------显示均衡化前后的图像---------------
cv2.imshow("original",img)
cv2.imshow("result",equ)
#-----------显示均衡化前后的直方图---------------
plt.figure("原始图像直方图") #构建窗口
plt.hist(img.ravel(),256)
plt.figure("均衡化结果直方图") #构建新窗口
plt.hist(equ.ravel(),256)
plt.show()
#----------等待释放窗口---------------------
cv2.waitKey()
cv2.destroyAllWindows()

insira a descrição da imagem aqui
Pode-se observar pelos resultados que o contraste é óbvio: antes da equalização do histograma, a imagem geral é mais clara
; após a equalização, o brilho da imagem fica mais equilibrado. O contraste entre os histogramas das duas imagens é menos óbvio. Isso realmente reflete que a equalização se refere ao resultado da consideração abrangente de probabilidade estatística e HVS.

insira a descrição da imagem aqui
insira a descrição da imagem aqui
Aqui está uma explicação simples:

  • No histograma da imagem original, a maioria dos valores de pixel está concentrada à direita (linhas densas). Isso mostra que há muitos pixels no intervalo [200,255] na imagem, e a imagem é relativamente clara.

  • No histograma equalizado, os pixels à esquerda são mais densos e os pixels à direita são relativamente esparsos. No entanto, de fato, o olho humano não consegue perceber claramente as diferenças sutis nos valores de pixel, então podemos considerar valores de pixel semelhantes como o mesmo valor de pixel, de modo que um histograma semelhante à Figura 13-29 seja obtido. Neste momento, a distribuição dos níveis de cinza no histograma é relativamente equilibrada e é um histograma equilibrado e consistente.

Acho que você gosta

Origin blog.csdn.net/hai411741962/article/details/132235279
Recomendado
Clasificación