Simulación de formación de imagen + restauración de imagen#
En este cuaderno, ensamblamos artificialmente una imagen de microscopio a partir de núcleos simulados, ruido y fondo. Posteriormente, utilizamos técnicas clásicas de procesamiento de imágenes para eliminar el ruido y el fondo.
import pyclesperanto_prototype as cle
import numpy as np
image_size = (100, 100)
# noise configuration
noise_level = 2
# background configuration
camera_offset = 100
background_sigma = 25
background_intensity = 5
# nuclei configuration
nuclei_radius = 5
nuclei_blur_sigma = 1
nuclei_number = 10
nuclei_intensity = 5
# by pinning the random seed, we can make the code repeatable
np.random.seed(42)
Ruido#
Aquí asumimos que el ruido en la imagen sigue una distribución de Poisson, una suposición común en microscopía.
noise_image = np.random.poisson(noise_level, image_size)
cle.imshow(noise_image, colorbar=True)
Fondo#
La intensidad de fondo en las imágenes de microscopía de fluorescencia típicamente proviene de luz fuera de foco. Podemos simular esto colocando fuentes de luz como píxeles individuales y difuminándolas con un filtro gaussiano. Además, muchas cámaras de microscopio tienen un llamado offset de cámara. Ningún píxel tendrá nunca una intensidad por debajo de este valor.
# create empty image
background = np.zeros(image_size)
# place light sources
background[20, 10] += 1
background[50, 80] += 1
background[60, 50] += 1
# blur them massively
background = cle.gaussian_blur(background, sigma_x=background_sigma, sigma_y=background_sigma)
# normalize the image so that the maximum intensity has a defined value
background = background / background.max() * background_intensity
# add camera offsert
background = background + camera_offset
background
|
|
cle._ image
|
Núcleos#
A continuación, colocamos núcleos en una imagen en posiciones aleatorias. Los difuminamos un poco para simular la función de dispersión de punto del microscopio.
# retrieve a defined number of random positions
nuclei_positions = np.random.random((nuclei_number, 2)) * image_size
# write 1 at these locations
nuclei_image = cle.pointlist_to_labelled_spots(nuclei_positions.T, np.zeros(image_size))
nuclei_image = (nuclei_image > 0) * nuclei_intensity
# enlarge the nuclei by a define radius
nuclei_image = cle.maximum_sphere(nuclei_image, radius_x=nuclei_radius, radius_y=nuclei_radius)
# blur the image to make it look more realistic
nuclei_image = cle.gaussian_blur(nuclei_image, sigma_x=nuclei_blur_sigma, sigma_y=nuclei_blur_sigma)
nuclei_image
|
|
cle._ image
|
Formación de la imagen#
Una imagen de microscopía es la suma de la escena y los efectos descritos anteriormente.
sum_image = np.asarray(noise_image + background + nuclei_image)
cle.imshow(sum_image, colorbar=True)
Segmentación de imagen#
Si ahora aplicáramos un algoritmo de segmentación a esta imagen tal como está, podría llevar a un resultado incorrecto.
binary = cle.threshold_otsu(sum_image.astype(np.float32))
binary
|
|
cle._ image
|
Eliminación del fondo#
Para solucionar este problema, necesitamos eliminar primero la intensidad del fondo.
background_removed = cle.top_hat_box(sum_image, radius_x=10, radius_y=10)
background_removed
|
|
cle._ image
|
Eliminación del ruido#
También podemos eliminar el ruido de la imagen.
noise_removed1 = cle.mean_sphere(sum_image, radius_x=3, radius_y=3)
noise_removed1
|
|
cle._ image
|
Y esto también se puede hacer en la imagen con el fondo sustraído.
noise_removed = cle.mean_sphere(background_removed, radius_x=3, radius_y=3)
noise_removed
|
|
cle._ image
|
Segmentación de imagen II#
Después de corregir la imagen, podemos intentar la segmentación nuevamente.
binary2 = cle.threshold_otsu(noise_removed.astype(np.float32))
binary2
|
|
cle._ image
|
# sneak preview: watershed
import napari_segment_blobs_and_things_with_membranes as nsbatwm
binary3 = nsbatwm.split_touching_objects(binary2)
binary3
<__array_function__ internals>:180: RuntimeWarning: Converting input from bool to <class 'numpy.uint8'> for compatibility.
|
|
nsbatwm made image
|