Solución:
Si desea cambiar el rango a [0, 1], asegúrese de que el tipo de datos de salida sea float
.
image = cv2.imread("lenacolor512.tiff", cv2.IMREAD_COLOR) # uint8 image
norm_image = cv2.normalize(image, None, alpha=0, beta=1, norm_type=cv2.NORM_MINMAX, dtype=cv2.CV_32F)
Cuando normaliza una matriz usando NORM_L1, está dividiendo el valor de cada píxel por la suma de los valores absolutos de todos los píxeles de la imagen. Como resultado, todos los valores de píxeles se vuelven mucho menores que 1 y se obtiene una imagen en negro. Pruebe NORM_MINMAX en lugar de NORM_L1.
Las otras respuestas normalizan una imagen basada en el imagen completa. Pero si su imagen tiene un color predominante (como el negro), enmascarará las características que está tratando de mejorar, ya que no será tan pronunciado. Para evitar esta limitación, podemos normalizar la imagen en función de una subsección de la región de interés (ROI). Básicamente, normalizaremos en función de la sección de la imagen que queremos mejorar en lugar de tratar por igual cada píxel con el mismo peso. Tomemos, por ejemplo, esta imagen de la tierra:
Imagen de entrada ->
Normalización basada en la imagen completa
Si queremos realzar las nubes normalizando en base a la imagen completa, el resultado no será muy nítido y estará sobre saturado debido al fondo negro. Las características a mejorar se pierden. Entonces, para obtener un mejor resultado, podemos recortar un ROI, normalizar en función del ROI y luego aplicar la normalización de nuevo a la imagen original. Digamos que recortamos el ROI resaltado en verde:
Esto nos da este ROI
La idea es calcular la desviación media y estándar del ROI y luego recortar el marco en función del rango inferior y superior. Además, podríamos usar un desplazamiento para ajustar dinámicamente la intensidad del clip. A partir de aquí normalizamos la imagen original a esta nueva gama. Aquí está el resultado:
Antes ->
Después
Código
import cv2
import numpy as np
# Load image as grayscale and crop ROI
image = cv2.imread('1.png', 0)
x, y, w, h = 364, 633, 791, 273
ROI = image[y:y+h, x:x+w]
# Calculate mean and STD
mean, STD = cv2.meanStdDev(ROI)
# Clip frame to lower and upper STD
offset = 0.2
clipped = np.clip(image, mean - offset*STD, mean + offset*STD).astype(np.uint8)
# Normalize to range
result = cv2.normalize(clipped, clipped, 0, 255, norm_type=cv2.NORM_MINMAX)
cv2.imshow('image', image)
cv2.imshow('ROI', ROI)
cv2.imshow('result', result)
cv2.waitKey()
La diferencia entre la normalización basada en la imagen completa y una sección específica del ROI se puede visualizar aplicando un mapa de calor al resultado. Note la diferencia en cómo se definen las nubes.
Imagen de entrada ->
mapa de calor
Normalizado en toda la imagen ->
mapa de calor
Normalizado en ROI ->
mapa de calor
Código de mapa de calor
import matplotlib.pyplot as plt
import numpy as np
import cv2
image = cv2.imread('result.png', 0)
colormap = plt.get_cmap('inferno')
heatmap = (colormap(image) * 2**16).astype(np.uint16)[:,:,:3]
heatmap = cv2.cvtColor(heatmap, cv2.COLOR_RGB2BGR)
cv2.imshow('image', image)
cv2.imshow('heatmap', heatmap)
cv2.waitKey()
Nota: Las coordenadas del cuadro delimitador de ROI se obtuvieron usando cómo obtener las coordenadas del cuadro delimitador de ROI sin Guess & Check y el código de mapa de calor fue de cómo convertir una imagen en escala de grises en una imagen de mapa de calor con Python OpenCV