在 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 图像实际上会更快。
众所周知,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 图像实际上会更快。