在 DigitalMicrograph 中使用内部变量进行图像处理

Image manipulation with intrinsic variables in DigitalMicrograph

众所周知,DigitalMicrograph 中的内在变量虽然有点难以理解,但非常有用,尤其是在图像处理方面,它比传统的 for 循环快得多。我想知道这些变量是否能够完成以下任务:

(1) 过滤具有给定值范围的图像。例如,逐个像素地测量图像,如果像素值介于 5-10 之间,则将像素设置为 0。

(2) 将 3D 数据立方体投影到 2D 图像。例如,将所有能量通道投影到真实 space 中的二维平面以获得平均图像(对于 EDS 或 EELS 光谱图像)。这其实类似于DM中的“投影Z”功能

对于项目 2D 到 1D lineprofile,这可以通过以下方式实现:

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

3D 也可以吗?

感谢您的帮助。

这些内在变量并没有真正的奥秘。我会尽量给你一个运行-down

图像上的前体

当您编写如下脚本时:

image img
img = 10

幕后第二行的真正作用是:

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

它遍历图像数组的所有像素(它是内存中 1 维 值的 nPixel 列表,即使图像是 2D 或3D) 并将它们中的 each 设置为 10.

因此,如果您不使用 10 而使用其他图像,例如:

image img1, img2
img1 = img2

变成

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

img1的每个数组值得到img2数组的相应值。 因此,两张图片的大小必须相同,否则会报错。事实上,尽管实际值是值的一维列表,解释器将检查维度的数量和维度的大小是否也相同。您不能在这样的脚本代码中将 100x1 图像设置为等于 10x10 图像。

内在变量入门

这些只不过是像素坐标位置的占位符。以 icol 为例。评估时,它将替换为当前处理的像素的 X 坐标。例如脚本:

image img
img = icol

真的变成了

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

到目前为止,我们只在等式的右边使用了 icol,我们的“内部”for 循环遍历了所有 nPixels在左侧的图像。 但这不是条件。也可以像在您自己的示例中那样在左侧使用 icol,但它是如何工作的?

为了工作,icol 必须有明确的含义。必须清楚是指哪个像素的“x”坐标,有多少个像素。或者,换句话说:整个等式中的 Something 必须是固定大小的已知图像。 (当然,所有固定大小的已知图像必须具有相同的大小,就像在简单的 img1 = img2 情况下一样。)

因此不能这样写:

img[icol,0] = 10

但是可以这样写:

img1[icol,0] = img2 * icol

如何'translate'? img2 的大小已知,因此在整个 表达式 中(- 只是方程的另一个词,因为它在数学意义上并不是真正的方程。-) icol 指的是那个图像和大小。真正执行的代码变成:

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

在上面,索引单个值[i]意味着只取内存中数据的第i个值(这是一个一维列表),但索引两个[i,j]确实是在 (x/y)=(i/j) 寻址像素。该对在内部转换为一维列表的“真实”位置,只需 i + j * image_width.

但是现在再看看“翻译”的代码:它不失败需要什么? 好吧,这一次:img1[xCoordinate_of_pixel_i_of_img2,0] 必须存在。
img1 的宽度必须至少与 img2.

一样大

但即便如此,如果你仔细观察for循环,你会发现img1的值会被多次重写! img2 的第一行将被设置为 img1,但随后循环继续并且 img2 的第二行的第一个值也被写入 img1[xCoordinate_of_pixel_i_of_img2,0]
(因为img2第二行xCoordinate_of_pixel_i_of_img2又变成0了。)

而这正是您示例中的“投影”代码有效的原因,因为

Dst [icol, 0] += Src

真的是

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

即你正在逐行累加。

真题答案

广告 1)

No, intrinsic variables deal with the position in an image, not its intensity values. But thresholding by value is even simpler in scripting. You just need a ternary operator (or the 'tert()' command, which is the same.)

Simply use:

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

or equivalently:

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

The operation is again performed pixel-by-pixel and the check is thus performed for each pixel's value - replacing the pixel by 0 if the condition isn't met, and keeping the value otherwise.

广告 2)

Yes, it directly extends from your example. You just have:

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

备注 1

但是,它并没有扩展到4D和5D。原因是,虽然 img[x]img[x,y]img[x,y,z] 被定义为表示 1D、2D 和 3D 中的值,但具有 4 个参数的语法 img[t,l,b,r] 已经是为指定二维图像中的矩形区域而定义。

注2

使用内部变量比编写脚本 for 循环快很多(真的很多!)。但是,这不是您可以禁食的时间。原因是,这样的表达式只会在单个线程上计算。然而,脚本具有内部多线程功能。因此,在一个坐标上进行脚本循环并汇总使用 slice2 命令提取的 2D 图像实际上会更快。