Brillo y Contraste#

Al visualizar imágenes en cuadernos Jupyter, es importante mostrarlas de manera que el lector pueda ver de lo que estamos escribiendo. Por lo tanto, ajustar el brillo y el contraste es importante. Podemos hacer esto modificando el rango de visualización, el rango de valores de gris mostrados.

Para fines de demostración, utilizamos la imagen de ejemplo cells3d de scikit-image.

import numpy as np
import matplotlib.pyplot as plt
from skimage.data import cells3d

El conjunto de datos cells3d es una imagen 4D. Usando acceso a arrays, extraemos un solo corte 2D y lo mostramos.

image = cells3d()[30,0]
image.shape
(256, 256)
plt.imshow(image, cmap='gray')
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x1b3bba94a90>
../_images/2bcb7875f1dce717e64697cb1aa61f9616cc35dacc923f4b6b73722dd4a2b022.png

Observe que aquí la barra de colores va desde 0 hasta aproximadamente 45000. La función plt.imshow() de matplotlib ajusta el contraste de la imagen a los valores mínimos y máximos.

Los valores mínimos y máximos de píxeles también se pueden obtener de esta manera:

min_value = image.min()
max_value = image.max()
print('min value = ', min_value)
print('max value = ', max_value)
min value =  277
max value =  44092

Si queremos aumentar el brillo, es decir, la percepción de que la imagen está emitiendo más luz, podemos configurar el rango de visualización estableciendo su mínimo vmin y máximo vmax. Esto mejora la visibilidad de las membranas.

plt.imshow(image, cmap='gray', vmax=10000)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x1b3bbb1dbb0>
../_images/8149ed3beb84e89872d2c2a89cb66f0e39ee1a57892f2d236e37239c0af8b187.png

Ajustando la visualización independientemente de la imagen específica#

La próxima imagen que abramos puede tener, o no, un rango de valores de gris similar. Por lo tanto, podríamos inspeccionar el histograma de la imagen y adivinar un mejor umbral manualmente.

plt.hist(image.ravel())
(array([5.8622e+04, 5.6930e+03, 9.7800e+02, 1.6900e+02, 5.5000e+01,
        1.0000e+01, 5.0000e+00, 1.0000e+00, 2.0000e+00, 1.0000e+00]),
 array([  277. ,  4658.5,  9040. , 13421.5, 17803. , 22184.5, 26566. ,
        30947.5, 35329. , 39710.5, 44092. ]),
 <BarContainer object of 10 artists>)
../_images/d44ffd39ecd6ea006e2fb16e609b9cb0089641b9a1b5f471f9d83a108305e746.png

Los histogramas de imágenes a menudo se muestran con una escala logarítmica.

plt.hist(image.ravel(), log=True)
(array([5.8622e+04, 5.6930e+03, 9.7800e+02, 1.6900e+02, 5.5000e+01,
        1.0000e+01, 5.0000e+00, 1.0000e+00, 2.0000e+00, 1.0000e+00]),
 array([  277. ,  4658.5,  9040. , 13421.5, 17803. , 22184.5, 26566. ,
        30947.5, 35329. , 39710.5, 44092. ]),
 <BarContainer object of 10 artists>)
../_images/390cc18dcf90c400508434856b86afeef6268377c02979413dacdb4cf315d66d.png

Obviamente, esta imagen tiene muchos valores de gris oscuros (< 20000) y pocos valores > 40000.

Podría tener sentido configurar la visualización utilizando un porcentaje. Supongamos que queremos visualizar la imagen de manera que el 95% de los píxeles estén dentro del rango. Podemos hacer esto usando el método percentil de numpy. También volveremos a los percentiles al final del semestre.

upper_limit = np.percentile(image, 95)
upper_limit
6580.0
plt.imshow(image, cmap='gray', vmax=upper_limit)
plt.colorbar()
<matplotlib.colorbar.Colorbar at 0x1b3bd17e670>
../_images/900b83be2052164812a59f814411961e6a79a3a890adfb8b7041a4b0e79bb58b.png

Ejercicio#

El conjunto de datos cells3d contiene otro canal que muestra los núcleos de las células. Visualízalo de manera que el 99% de los valores de gris más bajos se visualicen adecuadamente.

nuclei = cells3d()[30,1]
nuclei.shape
(256, 256)