Determinación de la función de dispersión de punto a partir de una imagen de cuentas mediante promediado#
Para deconvolucionar correctamente una imagen de microscopía, debemos determinar la función de dispersión de punto (PSF) del microscopio.
Ver también
import numpy as np
from skimage.io import imread, imsave
from pyclesperanto_prototype import imshow
import pyclesperanto_prototype as cle
import pandas as pd
import matplotlib.pyplot as plt
Los datos de imagen de ejemplo utilizados aquí fueron adquiridos por Bert Nitzsche y Robert Haase (ambos del MPI-CBG en ese momento) en la Instalación de Microscopía de Luz del MPI-CBG. Solo para completar, el tamaño de vóxel es 0.022x0.022x0.125 µm^3.
bead_image = imread('../../data/Bead_Image1_crop.tif')
bead_image.shape
(41, 150, 150)
Nuestra imagen de ejemplo muestra cuentas fluorescentes, idealmente con un diámetro menor que la resolución del sistema de imagen. Además, las cuentas deberían emitir luz en la misma longitud de onda que la muestra que nos gustaría deconvolucionar más adelante. En el siguiente recorte de imagen vemos cuatro cuentas fluorescentes. Se recomienda capturar un campo de visión más grande, con al menos 25 cuentas. También asegúrese de que las cuentas no se peguen entre sí y estén distribuidas de forma dispersa.
imshow(cle.maximum_x_projection(bead_image), colorbar=True)
imshow(cle.maximum_y_projection(bead_image), colorbar=True)
imshow(cle.maximum_z_projection(bead_image), colorbar=True)
Para determinar una PSF promedio, técnicamente podemos recortar todas las cuentas individuales, alinearlas y luego promediar las imágenes. Por lo tanto, segmentamos los objetos y determinamos su centro de masa.
# Segmentar objetos
label_image = cle.voronoi_otsu_labeling(bead_image)
imshow(label_image, labels=True)
# determinar el centro de masa para cada objeto
stats = cle.statistics_of_labelled_pixels(bead_image, label_image)
df = pd.DataFrame(stats)
df[["mass_center_x", "mass_center_y", "mass_center_z"]]
| mass_center_x | mass_center_y | mass_center_z | |
|---|---|---|---|
| 0 | 30.107895 | 73.028938 | 23.327475 |
| 1 | 44.293156 | 111.633430 | 23.329062 |
| 2 | 76.092850 | 82.453033 | 23.299677 |
| 3 | 125.439606 | 35.972496 | 23.390951 |
Promediado de PSF#
A continuación, iteraremos sobre las cuentas y las recortaremos trasladándolas a una imagen PSF más pequeña.
# configurar el tamaño de la futura imagen PSF
psf_radius = 20
size = psf_radius * 2 + 1
# inicializar PSF
single_psf_image = cle.create([size, size, size])
avg_psf_image = cle.create([size, size, size])
num_psfs = len(df)
for index, row in df.iterrows():
x = row["mass_center_x"]
y = row["mass_center_y"]
z = row["mass_center_z"]
print("Cuenta", index, "en posición", x, y, z)
# mover PSF a la posición correcta en una imagen más pequeña
cle.translate(bead_image, single_psf_image,
translate_x= -x + psf_radius,
translate_y= -y + psf_radius,
translate_z= -z + psf_radius)
# visualizar
fig, axs = plt.subplots(1,3)
imshow(cle.maximum_x_projection(single_psf_image), plot=axs[0])
imshow(cle.maximum_y_projection(single_psf_image), plot=axs[1])
imshow(cle.maximum_z_projection(single_psf_image), plot=axs[2])
# promediar
avg_psf_image = avg_psf_image + single_psf_image / num_psfs
Bead 0 at position 30.107894897460938 73.02893829345703 23.32747459411621
Bead 1 at position 44.293155670166016 111.63343048095703 23.32906150817871
Bead 2 at position 76.09284973144531 82.45303344726562 23.2996768951416
Bead 3 at position 125.43960571289062 35.972496032714844 23.39095115661621
La PSF promedio se ve así:
fig, axs = plt.subplots(1,3)
imshow(cle.maximum_x_projection(avg_psf_image), plot=axs[0])
imshow(cle.maximum_y_projection(avg_psf_image), plot=axs[1])
imshow(cle.maximum_z_projection(avg_psf_image), plot=axs[2])
avg_psf_image.min(), avg_psf_image.max()
(0.0, 94.5)
Después de determinar una PSF bien centrada, podemos guardarla para su reutilización posterior. Antes de hacer eso, normalizamos la PSF. El objetivo es tener una imagen donde la intensidad total sea 1. Esto asegura que una imagen que se deconvoluciona usando esta PSF más adelante no modifique el rango de intensidad de la imagen.
normalized_psf = avg_psf_image / np.sum(avg_psf_image)
imshow(normalized_psf, colorbar=True)
normalized_psf.min(), normalized_psf.max()
(0.0, 0.0006259646)
imsave('../../data/psf.tif', normalized_psf)
C:\Users\rober\AppData\Local\Temp\ipykernel_16716\3265681491.py:1: UserWarning: ../../data/psf.tif is a low contrast image
imsave('../../data/psf.tif', normalized_psf)