ImageJ: procesamiento multidimensional#
¡Trabajo en progreso!
Esta sección aún no está completa. En realidad, por ahora es sólo una colección dispersa de pensamientos.
Show code cell content
%load_ext autoreload
%autoreload 2
# Default imports
import sys
sys.path.append('../../../')
from helpers import *
from matplotlib import pyplot as plt
from myst_nb import glue
import numpy as np
from scipy import ndimage
Introducción#
Esta sección ofrece una breve descripción general de algunas cosas en las que pensar cuando se trabaja con pilas z y series de tiempo en ImageJ.
Operaciones de puntos, contraste y conversión.#
Las operaciones puntuales son sencillas: dependen sólo de píxeles individuales, por lo que el número de dimensiones no es importante. La aritmética de imágenes que involucra una pila 3D y una imagen 2D también se puede realizar en ImageJ usando
, donde se aplica la operación que involucra la imagen 2D. a cada porción de la pila 3D por turno. Otras opciones, como el filtrado y el establecimiento de umbrales, son posibles, pero conllevan consideraciones adicionales y, a menudo, costos computacionales significativamente más altos.Configurar la LUT de una imagen 3D requiere especial cuidado. La herramienta normal Reset o Auto. Optimizar la pantalla para un solo segmento no significa necesariamente que el resto de la pila se verá razonable si el brillo cambia mucho. es una mejor opción, ya que aquí puedes especificar que se debe utilizar la información de toda la pila. También puedes especificar el porcentaje de píxeles que deben saturarse (recortarse) para su visualización, es decir, aquellos que deben mostrarse con el primer o último color en la LUT. Mientras Normalize y Equalize histogram no estén seleccionados, los valores de píxeles no se deben cambiar.
solo toma en consideración el segmento que se muestra actualmente al presionarDe forma predeterminada, el porcentaje de píxeles saturados en
está establecido en 0.4. ¿Por qué se podría elegir esto en lugar de 0?Si el porcentaje de píxeles saturados es 0, entonces los valores mínimo y máximo de píxeles en toda la imagen recibirán el primer y último color LUT respectivamente, y todos los demás colores se dedicarán a valores intermedios. Esto es sensible a los valores atípicos y, a menudo, da como resultado imágenes con poco contraste. Generalmente es mejor aceptar una pequeña cantidad de saturación visual para dar más colores LUT a los valores de píxeles entre los extremos.
Conversión de profundidades de bits de imágenes multidimensionales
Como se describe en Types & bit-depths, los valores de rango de visualización mínimo y máximo se utilizan de forma predeterminada al reducir la profundidad de bits de una imagen. Para minimizar la pérdida de información, estos normalmente deben establecerse en los valores de píxeles mínimo y máximo dentro de la imagen; de lo contrario, los valores se recortarán.
En 2D es suficiente presionar Reset en la ventana , ¡pero en 3D esto solo funciona si los valores mínimo y máximo de toda la pila aparecen en el segmento actual!
Por esta razón, es una buena práctica ejecutar
antes de reducir la profundidad de bits de las pilas, establecer la saturación en 0 y usar toda la pila. Esto significa que no se recortarán píxeles en el output (aunque se seguirán produciendo cambios de escala y redondeo).Filtrado 3D#
Naturalmente, muchos filtros se prestan a aplicarse en tantas dimensiones como sea necesario. Por ejemplo, un filtro medio de 3×3 puede convertirse fácilmente en un filtro de 3×3×3 si se permite el promedio entre secciones. Es importante destacar que luego reemplaza cada píxel por el promedio de 27 valores, en lugar de 9.
Esto implica que la reducción de ruido es algo similar a la de aplicar un filtro de 5×5 (25 valores), pero con un poco menos de desenfoque en 2D y un poco más en la tercera dimensión. Varios filtros 3D están disponibles en el submenú
.Filtros rápidos y separables#
utiliza este enfoque.
Filtros rápidos y la transformada de Fourier
No todos los filtros lineales son separables y la aplicación de un filtro lineal grande y no separable también puede llevar mucho tiempo. Sin embargo, cuando este es el caso, se puede utilizar un método completamente diferente para obtener el mismo resultado utilizando la transformada de Fourier, donde la velocidad ya no depende tanto del tamaño del filtro. Desafortunadamente, el método de Fourier no se puede utilizar para filtros no lineales como el filtro de mediana.
Dimensiones e isotropía#
Si se aplica un filtro en 3D en lugar de 2D, puede parecer natural definirlo con el mismo tamaño en la tercera dimensión que en las dos originales. Pero para una pila z, el espacio entre cortes suele ser mayor que el ancho y el alto de un píxel. Y si la tercera dimensión es el tiempo, entonces utiliza otra escala completamente diferente. Por lo tanto, normalmente es necesario pensar más en qué tamaños tienen más sentido.
En algunos comandos (por ejemplo,
), hay una opcion {guilabel}”Use calibration” para determinar si los valores que ingresas están definidos en términos de las unidades que se encuentran en y, por lo tanto, corregidos según las dimensiones de píxeles almacenadas. En otros lugares (por ejemplo, ) las unidades son píxeles, secciones en z, y puntos de tiempo, por lo que tu eres responsable de descubrir cómo compensar las diferentes escalas y unidades.Umbral de datos multidimensionales#
Al establecer un umbral en una imagen con más de 2 dimensiones usando el comando
, es necesario elegir si el umbral debe determinarse a partir del histograma de toda la pila, o solo desde el corte 2D actualmente visible. En este último caso, también se te preguntará si se debe utilizar el mismo umbral para cada segmento o si se debe calcular de nuevo para cada segmento según el histograma del segmento. En algunas circunstancias, estas elecciones pueden tener un impacto muy grande en el resultado.Cuando estableces el umbral de una pila, tienes la opción de elegir Stack Histogram. Luego, cuando eliges Apply, se te preguntará si deseas Calculate Threshold for Each Image. ¿Qué diferencia esperas que hagan estas dos opciones y qué combinaciones usarías para:
una pila que consta de imágenes 2D de diferentes canales de color
una pila z
una serie de tiempo
Nota: Echa un vistazo a lo que sucede cuando haces click en Auto mientras te desplaza por un canal de la pila , con y sin Stack Histogram seleccionado. Tendrás que dividir los canales para esto porque ImageJ actualmente se niega a establecer un umbral para imágenes multicanal con dimensiones adicionales (lo que ayuda a evitar cierta confusión). Dark Background siempre debe estar seleccionado aquí.
Si se marca Stack Histogram, los umbrales se calculan a partir de un histograma de todos los píxeles de toda la pila de imágenes; de lo contrario, se utiliza únicamente el histograma del segmento de imagen que se muestra actualmente.
¡PERO! Si se elige Calculate Threshold for Each Image, esto se ignora: el umbral siempre lo determina el método automático seleccionado utilizando únicamente el histograma del segmento correspondiente.
Por lo tanto, las combinaciones más sensatas de opciones de umbral a utilizar dependen del tipo de datos.
canales de color: a menudo no hay una buena razón para suponer que la cantidad de fluorescencia en diferentes canales de color será similar, por lo que los umbrales deben calcularse a partir de cada canal de forma independiente.
z-Stacks: normalmente es una buena idea utilizar el histograma de pila con z-stacks. Si no lo haces, tu umbral se verá afectado por cualquier segmento que estés viendo en el momento del umbral, lo que introduce una fuente de variabilidad potencialmente extraña en los resultados. Probablemente no sea una buena idea calcular un nuevo umbral para cada segmento, porque esto llevaría a que se detecte al menos algo en cada segmento. Pero en los cortes exteriores puede que sólo haya desenfoque y ruido, ¡en cuyo caso no debería detectarse nada!
Serie temporal: en una serie temporal, el blanqueamiento a veces puede hacer que la imagen se oscurezca con el tiempo. En tal caso, el uso del histograma de pila podría provocar que menos píxeles superen el umbral en momentos posteriores simplemente por este motivo, y puede ser mejor volver a calcular el umbral para cada imagen. Por otro lado, si las imágenes se normalizaron previamente de alguna manera para compensar el blanqueamiento [^fn_1], entonces el umbral de pila podría ser preferible nuevamente. Es complicado.
Hay otra cuestión de implementación que requiere atención. Cuando se marca Dark Background y se calcula un umbral automático, lo único que realmente importa es el umbral bajo: el umbral alto siempre se establece en el máximo en el histograma. para garantizar que todos los píxeles más brillantes se designen como «primer plano» en el resultado. Sin embargo, si no se utiliza Stack Histogram, entonces, para imágenes que no sean de 8 bits, los histogramas se calculan utilizando los píxeles mínimo y máximo en el corte y, en consecuencia, el umbral alto no puede ser mayor que este valor máximo (observa cómo cambia el valor del umbral alto en a medida que calculas los umbrales automáticos para diferentes sectores). Esto significa que cualquier píxel más brillante estará fuera del rango de umbral (y, por lo tanto, del «fondo») si se produce en un segmento diferente. Esto puede provocar que aparezcan agujeros en las partes más brillantes de las estructuras y probablemente no sea lo que desea. Una situación similar ocurre con el umbral bajo cuando Dark Background no está marcado.
Medidas en datos 3D#
ImageJ tiene un buen soporte para realizar mediciones en 2D, particularmente los comandos
y . Este último puede manejar felizmente imágenes 3D, pero solo creando y midiendo ROI 2D de forma independiente en cada corte. Alternativamente, es como aplicar a cada corte de forma independiente, realizando mediciones en toda la imagen o en cualquier ROI. También trazará los valores medios de píxeles, pero incluso si no lo deseas especialmente, el comando puede resultar útil. Sin embargo, si se debieran realizar mediciones únicas para objetos individuales que se extienden a lo largo de múltiples cortes, ninguna de estas opciones sería suficiente.Show code cell content
fig = create_figure(figsize=(6, 4))
show_image('images/widest_roi_1.png', pos=131)
show_image('images/widest_roi_2.png', pos=132)
show_image('images/widest_roi_3.png', pos=133)
glue_fig('fig_multidimensional_widest', fig)
Supongamos que tienes una célula, un núcleo o alguna otra estructura grande en 3D en una pila z y deseas dibujar el ROI 2D más pequeño que lo contenga completamente en cada segmento. A continuación se muestra un ejemplo de la estructura verde en la imagen de muestra
.¿Cómo crearías ese ROI y estarías seguro/a de que es lo suficientemente grande para todos los sectores?
Mi estrategia sería crear una proyección z (intensidad máxima) y luego dibujar el ROI en esto o, preferiblemente, crear el ROI mediante un umbral usando Wand. Este ROI luego se puede transferir a la pila original, ya sea a través del ROI Manager o .
y la herramientaHistogramas y recorte de umbral#
Una forma de medir en 3D es utilizar el comando
y especificar que se debe incluir toda la pila; esto proporciona algunas estadísticas básicas, incluyendo el número total, la media, desviación mínima, máxima y estándar de los píxeles [^fn_2]. Esto respetará los límites de un ROI 2D si se ha dibujado uno.Este es un comienzo, pero no se ajustará a los cambios en los límites del objeto en cada plano 2D. Un mejor enfoque podría ser usar Apply para generar una imagen binaria. Más bien, en selecciona Limit to threshold. Luego, cuando calcules el histograma de la pila (o presiones para 2D), solo se incluirán en las estadísticas los píxeles por encima del umbral. Solo asegúrate de restablecer el Limit to threshold más adelante.
para establecer un umbral que identifique el objeto, pero no presione¿Cómo se puede traducir el número total de píxeles de un objeto a su volumen, p.ej. en µm3? Piensa un poco en qué tan preciso será tu método.
Podrías tratar cada píxel como un cuboide rectangular, con un volumen igual a ancho de píxel_×_alto de píxel_×_profundidad de voxel (como se indica en 3D Objects Counter al medir volúmenes.
). Luego multiplica esto por la cantidad de píxeles dentro del objeto. Esto es lo que hace el pluginSiempre que desees comparar tamaños de objetos entre imágenes adquiridas con diferentes tamaños de píxeles, esto es ciertamente mejor que simplemente tomar los recuentos de píxeles sin procesar como medidas de volumen. Sin embargo, es poco probable que sea muy preciso y no se debe confiar demasiado en las mediciones de volumen obtenidas de esta manera, especialmente cuando se trata de tamaños muy pequeños. También es probable que sean bastante sensibles al espaciado.
Usando NaNs
No soy un fanático de Limit to threshold, porque es probable que me olvide de restablecerlo después y posteriormente pueda medir cosas incorrectas durante los días siguientes.
Una alternativa que prefiero es establecer mi umbral en una copia de 32 bits de la imagen con la que estoy trabajando y luego Apply el umbral usando la opcion Set Background Pixels to NaN. Luego, todos los píxeles por debajo del umbral se excluirán automáticamente de cualquier medición que realice en el resultado, ya que «ya no son números» (consulte Thresholding para más detalles).
El contador de objetos 3D#
Actualmente, lo más parecido a
para medir objetos conectados en 3D integrado en Fiji es el contador de objetos 3D ( ) [^fn_3]. Su configuración (análoga a ) está en . Además de varias mediciones, proporciona imágenes etiquetadas como resultado, ya sea de los objetos completos o solo de sus píxeles centrales, opcionalmente con etiquetas o ampliadas para que sean más visibles.Encuentra regiones conectadas
es un comando principalmente para crear imágenes anotadas a partir de datos 3D con umbrales, que también pueden proporcionar el número total de píxeles por objeto. Si lo principal que deseas es la imagen anotada sin muchos más resultados, puede ser más rápido que .
Herramientas adicionales 3D
Para trabajar con datos 3D, puede resultar muy útil descargar “3D ImageJ Suite” desde https://imagej.net/plugins/3d-imagej-suite/. Esto no sólo incluye una gama de filtros rápidos y comandos para la segmentación, sino también una versión 3D del ROI Manager.
Si bien se creó para el análisis de imágenes óseas, BoneJ (https://bonej.org) también incluye algunos componentes que son útiles para aplicaciones generales, incluyendo un rápido Analizador de partículas 3D (otro alternativa al contador de objetos 3D) y una herramienta para [interpolar ROI en cortes de imagen] (https://bonej.org/utilities).