Opencv advanced 01-aplicación y ejemplo de histograma cv2.calcHist()

¿Qué es un histograma?

Un histograma es una representación gráfica utilizada para mostrar la distribución de valores individuales o rangos de valores en los datos. Divide los datos en una serie de intervalos (también conocidos como "bins" o "bins") y luego cuenta la frecuencia (o frecuencia) de los datos en cada intervalo. Los histogramas pueden ayudarnos a comprender mejor las características de distribución de los datos, incluida la tendencia central, la dispersión, etc.

Las características clave de los histogramas incluyen:

1. Eje horizontal (eje X) : El eje horizontal representa el rango numérico o intervalo de los datos. Cada intervalo suele estar representado por dos valores numéricos, por ejemplo, 0-10, 10-20, etc.

2. Eje vertical (eje Y ): El eje vertical representa la frecuencia (o frecuencia) de los datos en cada intervalo, es decir, la cantidad de veces que aparecen los datos en ese intervalo.

3. Gráfico de barras : El gráfico del histograma se compone de una serie de barras rectangulares. El ancho de cada barra rectangular representa el ancho del intervalo y la altura representa la frecuencia de los datos en el intervalo.

4. Datos continuos : 直方图适用于连续型数据como datos de medición, datos de tiempo, etc. 对于离散型数据,柱状图可能更为适合.

Los histogramas tienen aplicaciones importantes en muchos campos, incluidas las estadísticas, el procesamiento de imágenes, el análisis de datos, etc. En el procesamiento de imágenes, el histograma se puede utilizar para analizar la distribución del valor de píxel de la imagen, para realizar la mejora de la imagen, el ajuste del contraste, la segmentación de la imagen y otras operaciones. En estadística, los histogramas pueden ayudarnos a comprender la distribución de datos, como la distribución normal, la distribución sesgada, etc. Al observar el histograma, podemos tener una comprensión más profunda de las características de los datos, para tomar decisiones y análisis más precisos.

Significado del histograma en la imagen

Desde un punto de vista estadístico, el histograma es una función entre las características estadísticas del valor de gris en la imagen y el valor de gris de la imagen, y el histograma cuenta el número de ocurrencias de cada nivel de gris en la imagen.从直方图的图形上观察,横坐标是图像中各像素点的灰度级,纵坐标是具有该灰度级(像素值)的像素个数。

Por ejemplo, considere la imagen que se muestra en la Figura 13-1. Solo hay 9 píxeles en esta imagen, y hay 1, 2, 3, 4, 5, un total de 5 niveles de gris.

inserte la descripción de la imagen aquí

Cuente el número de ocurrencias de cada nivel de gris, como se muestra en la Tabla 13-1

inserte la descripción de la imagen aquí
Al dibujar un histograma, el nivel de gris se trata como el eje x, y el número de ocurrencias del nivel de gris se trata como el eje y, entonces se puede saber que:

  • Los datos del eje x son x=[1 2 3 4 5].
  • Los datos del eje y son y=[3 1 2 1 2].

De acuerdo con la relación anterior, se pueden dibujar el gráfico de líneas (imagen de la izquierda) y el histograma (imagen de la derecha) como se muestra en la Figura 13-2. En general, nos referimos al gráfico de línea recta de la izquierda y al histograma de la derecha como histogramas.

inserte la descripción de la imagen aquí

En el procesamiento real, el intervalo del eje x del histograma de la imagen es generalmente [0, 255], que corresponde a los 256 niveles de gris del mapa de bits de 8 bits; el eje y corresponde al número de píxeles con los niveles de gris correspondientes.

Por ejemplo, en la figura 13-3, la imagen superior es una imagen y la imagen inferior es su histograma correspondiente. Los puntos en la figura indican que estos píxeles se contarán hasta el nivel de gris correspondiente.

inserte la descripción de la imagen aquí

Aunque todas las imágenes de 8 bits tienen 256 niveles de gris (cada píxel puede tener 256 valores de gris), el número de píxeles que pertenecen a diferentes niveles de gris es muy diferente.

Por ejemplo, en la Figura 13-4, se puede ver en la figura que los histogramas de diferentes partes de la imagen son diferentes.
inserte la descripción de la imagen aquí

A veces también se utiliza un histograma normalizado para facilitar la presentación. En el histograma normalizado, el eje x aún representa los niveles de gris; el eje y ya no representa el número de ocurrencias de los niveles de gris, sino la frecuencia de ocurrencia de los niveles de gris.
Por ejemplo, para la Figura 13-1, se cuenta la frecuencia de aparición de cada nivel de gris:

La frecuencia de ocurrencias en escala de grises = el número de ocurrencias en escala de grises/número total de píxeles

Hay 9 píxeles en la Figura 13-1, por lo que los resultados estadísticos se muestran en la Tabla 13-2.

inserte la descripción de la imagen aquí

En el histograma normalizado, la suma de la frecuencia de cada nivel de gris es 1. Por ejemplo, en este caso:

inserte la descripción de la imagen aquí
Al dibujar un histograma, trate el nivel de gris como los datos del eje x y la frecuencia de su aparición como los datos del eje y, entonces podemos saber:

  • Los datos del eje x son x=[1 2 3 4 5]
  • Los datos del eje y son y=[3/9 1/9 2/9 1/9 2/9]

De acuerdo con la relación anterior, se puede dibujar el histograma normalizado que se muestra en la figura 13-5. Comparando la Figura 13-4 y la Figura 13-5, podemos ver que el histograma normalizado y el histograma son consistentes en apariencia, pero las etiquetas del eje y son diferentes.

En este ejemplo, en el histograma, las etiquetas que se muestran en el eje y son 1, 2, 3; en el histograma normalizado, las etiquetas que se muestran en el eje y son 1/9, 2/9, 3/9.

inserte la descripción de la imagen aquí
En el sitio web oficial de OpenCV, hay tres conceptos a los que se debe prestar atención: DIMS, BINS y RANGE.

  • DIMS: Indica el número de parámetros recopilados al dibujar el histograma. En general, solo hay un tipo de datos recopilados en el histograma, que es el nivel de gris. Por lo tanto, el valor es 1.
  • RANGO: Indica el rango de escala de grises a contar, generalmente [0, 255]. 0 corresponde a negro y 255 corresponde a blanco.
  • BINS: Número de subconjuntos de parámetros. En el proceso de procesamiento de datos, a veces es necesario dividir una gran cantidad de datos en varios grupos para su análisis.

Por ejemplo, para los niveles de gris en la Figura 13-1, es posible que desee hablar sobre dos valores de píxeles como un conjunto. De esta forma, toda la escala de grises se divide en tres grupos, concretamente { {1,2} , {3,4} , {5} }. La figura 13-6 muestra el histograma antes y después de la división.

inserte la descripción de la imagen aquí

Las imágenes en escala de grises también se pueden dividir de la manera descrita anteriormente. Por ejemplo, en una imagen en escala de grises, los 256 niveles de escala de grises en el intervalo [0, 255] se dividen en subconjuntos según cada grupo de 16 píxeles:

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

De acuerdo con el método anterior, todo el rango de escala de grises se puede dividir en 16 subconjuntos, específicamente:

Todo el rango de escala de grises = bin1 ∪ bin2 ∪…∪ bin16

Después de dividir los subconjuntos, el histograma generado por una imagen en escala de grises se muestra en la figura 13-7 (b1 en la figura representa bin1, b2 representa bin2, y así sucesivamente).

inserte la descripción de la imagen aquí
Los valores de BINS se analizan a continuación:

  • Para la Figura 13-1, hay 5 niveles de gris en la imagen original y su valor BINS es 5. Después de subdividir un grupo con 2 niveles de gris, se obtienen 3 subconjuntos, cuyo valor BINS es 3.
  • Para la imagen en escala de grises, el intervalo de escala de grises es [0, 255], hay 256 escalas de grises en total y su valor de BINS es 256; después de subdividir con 16 escalas de grises como grupo, su valor de BINS es 16.

Para decirlo sin rodeos, es el número de columnas

dibujar histograma

Python 的模块 matplotlib.pyplot 中的 hist()La función puede dibujar fácilmente el histograma, y ​​generalmente usamos esta función para dibujar el histograma directamente (esto también se usa en el aprendizaje automático). Además, OpenCV cv2.calcHist()函数puede calcular histogramas estadísticos y también puede
dibujar histogramas de imágenes sobre esta base. Estos dos métodos se analizan por separado a continuación.

Dibujar histograma usando Numpy

El módulo matplotlib.pyplot proporciona un marco similar al método de dibujo de MATLAB, que se puede utilizar matplotlib.pyplot.hist()函数(en adelante, la función hist()) para dibujar histogramas.

La función de esta función es dibujar un histograma según la fuente de datos y la agrupación de niveles de gris. Su formato de sintaxis básica es:

matplotlib.pyplot.hist(X,CONTENEDORES)

Los significados de los dos parámetros son los siguientes:

  • X: Fuente de datos, debe ser unidimensional. Las imágenes suelen ser bidimensionales y debe usar la función ravel() para procesar la imagen en una fuente de datos unidimensional antes de usarla como parámetro.

  • BINS: El valor específico de BINS, que indica la agrupación de niveles de gris .

La función de ravel() es reducir la dimensión de una matriz bidimensional a una matriz unidimensional. Por ejemplo, hay una imagen con valor:

inserte la descripción de la imagen aquí
Utilice la función ravel() para procesar un:

b = a.ravel()

b se puede obtener como:
inserte la descripción de la imagen aquí

Ejemplo: utilice la función hist() para dibujar un histograma de una imagen.

inserte la descripción de la imagen aquí
el código se muestra a continuación:

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

resultado de la operación:

inserte la descripción de la imagen aquí

Ejemplo: después de usar la función hist() para dividir el nivel de gris de una imagen en 16 grupos, dibuje el histograma de la imagen.

Cambie el 255 anterior a 16

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

inserte la descripción de la imagen aquí

Dibujar un histograma usando OpenCV

OpenCV proporciona la función cv2.calcHist() para calcular el histograma estadístico de la imagen, que puede contar la cantidad de píxeles en cada nivel de gris. Usando la función plot() en el módulo matplotlib.pyplot, los resultados estadísticos de la función cv2.calcHist() se pueden dibujar en un histograma

1. Use la función cv2.calcHist() para contar la información del histograma de la imagen.
La función cv2.calcHist() se usa para contar la información del histograma de la imagen y su formato de sintaxis es:

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

Los significados del valor devuelto y los parámetros en la función son:

  • hist: el histograma estadístico devuelto es una matriz unidimensional y los elementos de la matriz son el número de píxeles en cada nivel de gris.

  • imágenes: imágenes originales, que deben encerrarse entre "[ ]".

  • canales: especifica el número de canal. El número de canal debe estar entre "[ ]". Si la imagen de entrada es una imagen en escala de grises de un solo canal, el valor de este parámetro es [0]. Para imágenes a color, sus valores pueden ser [0], [1], [2], correspondientes a los canales B, G, R, respectivamente.

  • máscara: imagen de máscara. Al contar el histograma de toda la imagen, establezca este valor en Ninguno. Al contar el histograma de una determinada parte de la imagen, se necesita una imagen de máscara.

  • histSize: el valor de BINS, que debe encerrarse entre "[ ]". Por ejemplo, el valor de BINS es 256, debe usar "[256]" como valor de este parámetro.

  • rangos: el rango de valores de píxeles. Por ejemplo, una imagen en escala de grises de 8 bits tiene valores de píxeles en el rango [0, 255].

  • acumular: indicador acumulativo (acumulativo, superpuesto), el valor predeterminado es Falso. Si se establece en True, el histograma no se borrará al comienzo del cálculo y el cálculo es el resultado acumulativo de varios histogramas, que se utiliza para calcular el histograma de un grupo de imágenes
    . Este parámetro permite calcular un único histograma a partir de varios objetos o actualizar el histograma en tiempo real. Este parámetro es opcional y, por lo general, no es necesario configurarlo.

Ejemplo: utilice la función cv2.calcHist() para calcular el resultado del histograma estadístico de una imagen y observe la información del histograma estadístico obtenido.

el código se muestra a continuación:


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)

Los resultados de ejecución son los siguientes:
Tenga en cuenta que en la función cv2.calcHist() en este ejemplo:

  • El primer parámetro "[img]" indica la imagen original para dibujar el histograma, encerrada entre "[ ]".
  • El segundo parámetro indica qué información del histograma del canal se va a contar. La lectura de img en este ejemplo es una imagen en escala de grises, por lo que está
    representada por "[0]".
  • El tercer parámetro es la imagen de máscara, en este caso el valor es "Ninguno", lo que significa calcular el histograma de toda la imagen.
  • El cuarto parámetro "[16]" indica que el valor de BINS es 16, es decir, se divide en 16 grupos
  • El quinto parámetro “[0, 255]” indica que el rango de escala de grises es [0, 255].
<class 'numpy.ndarray'>
(16, 1)
16
[[ 12575.]
 [ 39591.]
 [ 56651.]
 [ 38932.]
 [ 29997.]
 [ 33472.]
 [ 46033.]
 [ 74555.]
 [199718.]
 [288966.]
 [136663.]
 [ 44440.]
 [ 20355.]
 [ 20691.]
 [  5578.]
 [   344.]]

Ejemplo: dibujar un histograma estadí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 de la operación:
inserte la descripción de la imagen aquí

Todas las funciones anteriores son para mostrar imágenes en histogramas.Hablemos de las funciones de aplicación de histogramas en el procesamiento de imágenes.

Ecualización de histograma

Si una imagen tiene todos los niveles de gris posibles y los niveles de gris de los valores de píxel se distribuyen uniformemente, entonces la imagen tiene un alto contraste y tonos de gris variables, niveles de gris ricos y una gran cobertura. En apariencia, estas imágenes tienen colores más ricos y no son demasiado oscuras ni brillantes.

La figura 13-22 muestra la comparación de una imagen antes y después de la ecualización del histograma. La imagen de la izquierda es la imagen original, que es relativamente oscura; la imagen de la derecha es la imagen después de la ecualización, y el color está relativamente equilibrado.

inserte la descripción de la imagen aquí

En el sitio web oficial de OpenCV, se comparan los histogramas antes y después de la ecualización de imágenes (es decir, la ecualización de histogramas), como se muestra en la Figura 13-23. Entre ellos, la imagen de la izquierda es el histograma de la imagen original. Se puede ver que el nivel de gris se concentra en el medio, y no hay píxeles más oscuros y más brillantes en la imagen; la imagen de la derecha es el histograma después de igualar el original imagen, y la distribución de píxeles es más equilibrada.

inserte la descripción de la imagen aquí

El objetivo principal de la ecualización de histogramas es mapear uniformemente el nivel de gris de la imagen original en todo el rango de nivel de gris y obtener una imagen con una distribución uniforme del nivel de gris. Esta ecualización no solo realiza el balance de probabilidad en las estadísticas del valor gris, sino que también realiza el balance visual en el Sistema Visual Humano (HVS).

Función de ecualización de histograma

OpenCV 使用函数 cv2.equalizeHist()实现直方图均衡化. La sintaxis de esta función es:

dst = cv2.equalizeHist( src )

En la fórmula:

  • dst es el resultado del proceso de ecualización del histograma.
  • src es una imagen sin procesar de un solo canal de 8 bits.

Ejemplo: utilice la función cv2.equalizeHist() para implementar la ecualización de histogramas.

Imagen original:
inserte la descripción de la imagen aquí
el código es el siguiente:

#-----------导入使用的模块---------------
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()

inserte la descripción de la imagen aquí
Se puede ver a partir de los resultados que el contraste es obvio: antes de la ecualización del histograma, la imagen general es más brillante
; después de la ecualización, el brillo de la imagen se vuelve más equilibrado. El contraste entre los histogramas de las dos imágenes es menos evidente. En realidad, esto refleja que la ecualización se refiere al resultado de una consideración integral de la probabilidad estadística y HVS.

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Aquí hay una explicación simple:

  • El histograma de la imagen original, la mayoría de los valores de píxeles se concentran a la derecha (líneas densas). Esto muestra que hay muchos píxeles en el intervalo [200,255] de la imagen y que la imagen es relativamente brillante.

  • En el histograma ecualizado, los píxeles de la izquierda son más densos y los píxeles de la derecha son relativamente dispersos. Sin embargo, de hecho, el ojo humano no puede percibir claramente las diferencias sutiles en los valores de píxel, por lo que podemos considerar valores de píxel similares como el mismo valor de píxel, por lo que se obtendrá un histograma similar a la Figura 13-29. En este momento, la distribución de los niveles de gris en el histograma está relativamente equilibrada y es un histograma equilibrado y consistente.

Supongo que te gusta

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