Como sabemos, las variables intrínsecas en DigitalMicrograph, aunque un poco difíciles de entender, son muy útiles, especialmente en la manipulación de imágenes, que es mucho más rápida que el bucle for convencional. Me pregunto si estas variables pueden realizar las siguientes tareas:

(1) Filtrar una imagen con un rango de valor determinado. Por ejemplo, mida una imagen píxel por píxel y luego establezca el píxel en 0 si su valor se encuentra entre 5 y 10.

(2) Proyecte un cubo de datos 3D en una imagen 2D. Por ejemplo, proyecte todos los canales de energía al plano 2D en el espacio real para obtener la imagen promedio (para EDS o EELS espectro-imagen). Esto es realmente similar a la función "Proyección Z" disponible en el DM.

En el caso del perfil de línea del proyecto 2D a 1D, esto se puede lograr mediante:

image Projection := RealImage ("Integrated lineprofile", 4, sizeX, 1)
Projection [icol, 0] += Img_source

¿Será posible también para 3D?

Gracias por tu ayuda.

2
DM Adventurer 23 nov. 2019 a las 12:31

1 respuesta

La mejor respuesta

No hay ningún misterio real para estas variables intrínsecas. Trataré de darte un descuido

Precursor de imágenes

Cuando escribes un guión como:

image img
img = 10

Lo que realmente hace en la segunda línea detrás de la cortina es:

for (i=0; i<nPixels; i++)
   img[i] = 10

Itera todos los píxeles de la matriz de imágenes (que es una lista unidimensional de valores nPixel en la memoria, incluso si la imagen es 2D o 3D) y establece cada de ellos a 10.

En consecuencia, si en lugar de 10 usarías una imagen diferente como:

image img1, img2
img1 = img2

Se vuelve

for (i=0; i<nPixels; i++)
   img1[i] = img2[i]

Cada valor de la matriz de img1 obtiene el valor correspondiente de la matriz de img2. Por lo tanto, las dos imágenes deben ser del mismo tamaño o obtendrá un error. De hecho, aunque los valores reales son una lista de valores 1D, el intérprete verificará que el número de dimensiones y los tamaños de las dimensiones también sean los mismos. No puede establecer una imagen de 100x1 igual a una imagen de 10x10 en un código de secuencia de comandos como este.

Introducción a las variables intrínsecas

Estos no son más que marcadores de posición para la posición de las coordenadas de un píxel. Tome icol por ejemplo. Cuando se evalúe, será reemplazado por la coordenada X del píxel en el que se está trabajando actualmente. Por ejemplo, el guión:

image img
img = icol

Realmente se convierte

for (i=0; i<nPixels; i++)
   img[i] = xCoordinate_of_pixel_i

Hasta ahora, hemos usado icol solo en el lado derecho de la ecuación, y nuestro bucle for "interno" cubre toda nPixels de la imagen de la izquierda. -lado. Pero esa no es una condición. Se puede usar icol también en el lado izquierdo como en su propio ejemplo, pero ¿cómo funciona entonces?

Para que funcione, debe haber un significado inequívoco de icol . Debe quedar claro a qué píxel se refiere la coordenada "x" y cuántos píxeles hay. O, en otros términos: Algo en la ecuación completa debe ser una imagen conocida de tamaño fijo. (Y, por supuesto, todas las imágenes conocidas de tamaño fijo deben ser del mismo tamaño, como en la situación img1 = img2 simple).

Por lo tanto, no se puede escribir algo como:

img[icol,0] = 10

Pero se puede escribir algo como:

img1[icol,0] = img2 * icol

¿Cómo se 'traduce'? img2 es de tamaño conocido, por lo que en toda la expresión (- solo otra palabra para la ecuación, porque en realidad no es una ecuación en el sentido matemático -) el icol se refiere a esa imagen y tamaño. El código real ejecutado entonces se convierte en:

for (i=0; i<nPixels_of_img2; i++)
   img1[xCoordinate_of_pixel_i_of_img2,0] = img2[i] * xCoordinate_of_pixel_i_of_img2

En lo anterior, indexar un solo valor [i] significa simplemente tomar el i-ésimo valor de los datos en la memoria (que es una lista 1D), pero indexar con dos [i,j] realmente es abordar los píxeles en ( x / y) = (i / j). El par se convierte internamente en la posición "real" de la lista 1D, simplemente por i + j * image_width.

Pero ahora mire el código "traducido" nuevamente: ¿Qué se requiere para que no falle? Bueno, por una vez: img1[xCoordinate_of_pixel_i_of_img2,0] debe existir.
img1 debe tener un ancho al menos tan grande como img2.

Pero aun así, si observa con cuidado el bucle for, notará que los valores de img1 se reescribirán varias veces. La primera fila de img2 se establecerá en img1, pero luego el ciclo continúa y el primer valor de la segunda fila de img2 también se escribe en img1[xCoordinate_of_pixel_i_of_img2,0].
(Porque xCoordinate_of_pixel_i_of_img2 vuelve a ser 0 en la segunda fila de img2).

Y esta es exactamente la razón por la que el código de "proyección" en su ejemplo funciona, porque

Dst [icol, 0] += Src

Realmente significa

for (i=0; i<nPixels_of_Src; i++)
   Dst[ xCoordinate_of_Src_of_pixel_i, 0 ] += src[i]

Es decir, estás sumando fila tras fila.

La pregunta real responde

Anuncio 1)

No, las variables intrínsecas se ocupan de la posición en una imagen, no de sus valores de intensidad. Pero establecer umbrales por valor es aún más simple en la creación de scripts. Solo necesita un operador ternario (o el comando 'tert ()', que es el mismo).

Simplemente use:

img = ( (img < 5) || (img > 10) ? img : 0 )

o equivalente:

img = tert( (img < 5) || (img > 10) , img , 0 )

La operación se realiza nuevamente píxel por píxel y, por lo tanto, se realiza la verificación para el valor de cada píxel, reemplazando el píxel por 0 si no se cumple la condición y manteniendo el valor en caso contrario.

Anuncio 2)

Sí, se extiende directamente a tu ejemplo. Tu solo tienes:

image Projection := RealImage ("Integrated planes", 4, sizeX, sizeY)
Projection [icol, irow, 0] += Img_source

Nota 1

Sin embargo, no se extiende a 4D y 5D. La razón es que, si bien img[x], img[x,y] y img[x,y,z] se definen como representando un valor en 1D, 2D y 3D, la sintaxis con 4 parámetros img[t,l,b,r] ya es definido para especificar un área rect en una imagen 2D.

Nota 2

El uso de variables intrínsecas es mucho (¡mucho!) Más rápido que hacer un bucle for programado. Sin embargo, no es el ayuno al que puede ir. La razón es que dicha expresión solo se calculará en un único hilo. Sin embargo, se recomiendan funciones de secuencias de comandos que internamente son de subprocesos múltiples. Por lo tanto, en realidad es más rápido tener un bucle programado sobre una coordenada y sumar imágenes 2D extraídas con el comando slice2.

0
Community 20 jun. 2020 a las 09:12