如何从数据集中任意提取特定的图像子集?

How to arbitrarily extract a specific subset of images from a dataset?

最近我打算操作一堆图像,目标是从那里提取特定的切片子集,例如仅偶数或奇数或任意索引,然后将它们保存到另一个数据集中。

在DM中,音量菜单中有很多有用的功能,但不幸的是,它们不能真正满足我想要做的事情。

我只是想知道这个想法是否可以通过脚本实现。

非常感谢您的提前帮助。

有两种方法可以解决,其中一种只适用于 3D 以下的数据,通常比另一种慢,但更灵活。 正如您一直在要求 arbitrary 子采样,我从那个选项开始,但第二个选项更有可能为您提供您想要的:orthogonal, regular 子采样。

如果您赶时间,简短的回答是:使用 SliceN 命令。


1) 使用表达式(任意子采样)

Individual pixel positions in an Image data (img) can be addressed using the notations

  • img[ X, 0 ] ... for 1D data at position X
  • img[ X, Y ] ... for 2D data at position X/Y
  • img[ X, Y, Z ] ... for 3D data at position X/Y/Z

请注意,即使这解决了单个数字,结果也是一个 表达式,大小为 1x11x1x1 而不是标量数,因此您 不能 做:number num = img[10,4]

但是,您可以使用一些小技巧来使用任何将表达式转换为单个数字的函数,例如 f.e。求和。所以你可以做到number num = sum(img[10,4])

那么这与您的问题有什么关系?那么,在上面的表达式中,我们使用标量值 XYZ,结果表达式是大小为 1x11x1x1,但是

You can use expressions of any size as X, Y, Z in this notations, as long as all of them are expressions of same size. The resulting addressed data is of this size with values references by the according coordinates.

这将通过下面的示例变得更加清楚。从一个简单的一维示例开始:

image img1D := RealImage( "TestData", 4, 100 )
image coord := RealImage( "Coordinates", 4, 10 )

img1D = 1000 + icol             // Just sum test data
coord = trunc(100*Random())     // random integer 0-99
image subImg :=  img1D[coord,0]

img1D.ShowImage()
coord.ShowImage()
subImg.ShowImage()

我们的测试数据 (img1D) 这里只是一个从 1000 到 1099 的线性图,使用 icol 表达式,在每个像素处,代表该像素的 X 坐标。

坐标图像 (coord) 包含 0 到 99 之间的随机整数值。

'magic' 发生在 subImg。我们使用以 coord 图像作为 X 坐标的表达式。该图像的大小为 10(x1),因此输出表达式的大小为 10(x1),我们将其分配给图像 [=36] =] 在显示之前。

请注意,我们构建的 expression 实际上只是指向图像的数据。我们可以使用该表达式 更改 数据中的这些点,而不是将其显示为新图像,而是使用:

img1D[coord,0] = 0


从这里开始,可以直接将示例扩展到 2D:

image img2D := RealImage( "TestData", 4, 30, 30 )
image coordX := RealImage( "Coordinates X", 4, 10 )
image coordY := RealImage( "Coordinates Y", 4, 10 )

img2D = 10000 + icol + irow * 100
coordX = trunc(30*Random())
coordY = trunc(30*Random())
img2D[coordX,coordY] = 0

coordX.ShowImage()
coordY.ShowImage()
img2D.ShowImage()


...和 ​​3D:

image img3D := RealImage( "TestData", 4, 30, 30, 30 )
image coordX := RealImage( "Coordinates X", 4, 10 )
image coordY := RealImage( "Coordinates Y", 4, 10 )
image coordZ := RealImage( "Coordinates Y", 4, 10 )

img3D = 10000 + icol + irow * 100 + iplane * 1000
coordX = trunc(30*Random())
coordY = trunc(30*Random())
coordZ = trunc(30*Random())
img3D[coordX,coordY,coordZ] = 0

coordX.ShowImage()
coordY.ShowImage()
coordZ.ShowImage()
img3D.ShowImage()

很遗憾,到此为止。

You can no longer do this type of addressing in 4D or 5D data, because expression with 4 parameters are already defined to address a rectangle region in 2D data as img[T,L,B,R]



2)使用SliceN(正交子采样)

Data subsets along the dimension directions of data can be addressed using the command SliceN and its simplified variants Slice1, Slice2 and Slice3.

SliceN 命令可能是我在处理数据时最喜欢的语言命令之一。起初看起来很吓人,但它是直截了当的。

让我们从一维提取的简化版本开始,Slice1

To extract 1D data from any data up to 3D with the Slice1 command, you need the following (-and these are exactly the 7 parameters used by the command-):

  • data source
  • start point in the source
  • sampling direction
  • sampling length
  • sampling step-size

The only thing you need to know on top of that is:

  • The start point is always defined as a X,Y,Z triplet, even if the data source is only 2D or 1D.
    0 is used for the not needed dimensions.
  • Directions are given as dimension index: 0 = X, 1 = Y, 2 = Z
  • Step-size can be negative to indicate opposite directions
  • The specified sampling must be contained within the source data.
    (You can not 'extrapolate')

所以提取 3D 数据集的 1D 数据的一个非常简单的例子是:

number sx = 20
number sy = 20
number sz = 20

image img3D := RealImage( "Spectrum Image", 4, sx, sy, sz )
img3D = 5000000 + icol + irow * 100 + iplane * 10000

number px = 5
number py = 7
image spec1D := Slice1( img3D, px,py,0, 2,sz,1 )

ShowImage( img3D )
ShowImage( spec1D )

这个例子展示了分析显微镜在处理“3D 光谱图像”数据时的一个非常典型的情况:在特定空间位置提取“1D 光谱”。

该示例针对空间点 px,py 执行了此操作。从该位置 (px,py,0) 的点开始,它沿 Z 方向 (2) 对数据 (sz) 的所有像素进行采样,步长为 1.

请注意,该命令再次 returns 源数据中的 表达式 ,您可以使用它来 set 值,只需使用 f.e.:

Slice1( img3D, px,py,0, 2,sz,1 ) = 0


使用命令 Slice2Slice3 的 2D 和 3D 数据扩展很简单。不是定义 one 输出方向,而是分别定义 twothree。每个都有三个数字:方向、长度、步长

以下示例提取“3D 光谱图像”的 "image plane":

number sx = 20
number sy = 20
number sz = 20

image img3D := RealImage( "Spectrum Image", 4, sx, sy, sz )
img3D = 5000000 + icol + irow * 100 + iplane * 10000

number pz = 3
image plane2D := Slice2( img3D, 0,0,pz, 0,sx,1, 1,sy,1 )

ShowImage( img3D )
ShowImage( plane2D )

下面的示例 "rotates" 3D 图像:

number sx = 6
number sy = 4
number sz = 3

image img3D := RealImage( "Spectrum Image", 4, sx, sy, sz )
img3D = 1000 + icol + irow * 10 + iplane * 100

image rotated := Slice3( img3D, 0,0,0, 0,sx,1, 2,sz,1, 1,sy,1 )

ShowImage( img3D )
ShowImage( rotated  )

You can get all sorts of rotations, mirroring, binning with these commands. If you want the full flexibility to get any expression up to 5D from any source data up to 5D, then you need the most versatile SliceN command.

它的工作原理完全相同,但是您需要指定源数据的维度和输出表达式的维度。然后,'starting' 点需要根据源数据维度的建议使用尽可能多的坐标来定义,并且每个输出维度需要一个三元组规范。

对于 N 维的源数据并想要输出 M 维,您需要:2 + N + 3*M 个参数。

例如,让我们从“4D 衍射图像”数据中提取特定空间位置的 "plane",该数据在 2D 扫描的每个空间位置存储 2D 图像:

number sx = 9
number sy = 9
number kx = 9
number ky = 9

image img4D := RealImage( "Diffraction Image", 4, sx, sy, kx, ky )
img4D = 50000 + icol + irow * 10 + idimindex(2)*100 + idimindex(3)*1000

number px = 3
number py = 4

image img2D := SliceN( img4D, 4, 2, px,py,0,0, 2,kx,1, 3,ky,1 )

ShowImage( img4D )
ShowImage( img2D )