Ecualización de histograma
La ecualización de imagenes tiene como objetivo mejorar la visualización de una imagen mediante un procedimiento que fomenta la uniforme existencia de intensidades dentro de la imagen. Dicha uniformidad permite aprovechar el todo el rango de valores que la imagen puede expresar y por tanto permite que esta incremente su contraste.
Imagen antes de la ecualización
Histograma antes de la ecualización
Función de probabilidad antes de la ecualización
Imagen después de la ecualización
Histograma despues de la ecualización
Función de probabilidad despues de la ecualización
Como se puede observar, la ecualización permite aprovechar el todo el rango de valores de intensidad de una imagen, lo cual en múltiples ocasiones facilita la clara precepción de las caracteristicas de la imagen de interes. Para implementar dicho procedimiento, solo es necesario seguir los siguientes pasos:
Obtener el histograma de la imagen
Calcular la función de probabilidad de la imagen
Evaluar los pixeles de la imagen en la función de probabilidad
Remapear la salida a la escala de la imagen (usualmente 255)
Script empleado en el ejemplo:
import cv2
import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
from scipy import interpolate
def main():
# Se carga la imagen a trabajar
imagen = cv2.imread('bosque.jpg')
# Se acomoda la informacion para ser trabajada por canales
canales = np.array(cv2.split(imagen))
col = ['b', 'g', 'r']
resultado = canales
hist_antes = np.zeros((3, 256))
hist_despu = np.zeros((3, 256))
fun_pro_antes = np.zeros((3, 256))
fun_pro_despu = np.zeros((3, 256))
# Se ecualiza cada canal de forma independiente
for i, canal in enumerate(canales):
# Se calcula el histograma del canal
hist = cv2.calcHist(canal, [0], None, [256], [0,256])
hist = np.transpose(hist)[0]
# Se guarda el histograma del canal
hist_antes[i] = hist
# Se calcula la funcion de probabilidad
fp = hist.cumsum()
fp = (fp/fp[-1])
# Se guarda la funcion de probabilidad del canal
fun_pro_antes[i] = fp
# Se pasa la imagen por la funcion de probabilidad y se remapea
resultado[i] = (fp[canal]*255).astype(int)
# Se calcula el histograma del canal ecualizado
hist = cv2.calcHist(resultado[i], [0], None, [256], [0,256])
hist = np.transpose(hist)[0]
# Se guarda el histograma del canal ecualizado
hist_despu[i] = hist
# Se calcula la funcion de probabilidad del canal ecualizado
fp = hist.cumsum()
fp = (fp/fp[-1])
# Se guarda la funcion de probabilidad del canal ecualizado
fun_pro_despu[i] = fp
imagen_ecualizada = cv2.merge(resultado)
# Se muestra la imagen original
plt.figure(dpi=300)
plt.tight_layout()
plt.axis('off')
plt.imshow(cv2.cvtColor(imagen, cv2.COLOR_BGR2RGB), vmin=0, vmax=255)
plt.show()
cv2.imwrite('Original.png', imagen)
# Se muestra la imagen ecualizada
plt.figure(dpi=300)
plt.tight_layout()
plt.axis('off')
plt.imshow(cv2.cvtColor(imagen_ecualizada, cv2.COLOR_BGR2RGB), vmin=0, vmax=255)
plt.show()
cv2.imwrite('Ecualizada.png', imagen_ecualizada)
#Se muestran los histogramas antes de procesar
plt.figure(figsize=(8, 6), dpi=300)
for i, hist in enumerate(hist_antes):
plt.plot(np.arange(256), hist, color = col[i])
plt.tight_layout()
plt.savefig('Histograma original.png', dpi=300, bbox_inches='tight')
plt.show()
#Se muestran los histogramas antes de procesar
plt.figure(figsize=(8, 6), dpi=300)
for i, hist in enumerate(hist_despu):
plt.plot(np.arange(256), hist, color = col[i])
plt.tight_layout()
plt.savefig('Histograma ecualizado.png', dpi=300, bbox_inches='tight')
plt.show()
#Se muestran los histogramas antes de procesar
plt.figure(figsize=(8, 6), dpi=300)
for i, fun_pro in enumerate(fun_pro_antes):
plt.plot(np.arange(256), fun_pro, color = col[i])
plt.tight_layout()
plt.savefig('Funcion de probabilidad original.png', dpi=300, bbox_inches='tight')
plt.show()
#Se muestran los histogramas antes de procesar
plt.figure(figsize=(8, 6), dpi=300)
for i, fun_pro in enumerate(fun_pro_despu):
plt.plot(np.arange(256), fun_pro, color = col[i])
plt.tight_layout()
plt.savefig('Funcion de probabilidad ecualizado .png', dpi=300, bbox_inches='tight')
plt.show()
if __name__ == '__main__':
sns.set_theme(style= 'darkgrid' )
main()