【问题标题】:How to arbitrarily extract a specific subset of images from a dataset?如何从数据集中任意提取特定的图像子集?
【发布时间】:2018-05-04 12:03:35
【问题描述】:

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

在 DM 中,音量菜单中有许多有用的功能,但不幸的是,它们无法真正完成我想做的事情。

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

非常感谢您提前提供的帮助。

【问题讨论】:

  • 我建议您针对您的问题发布初始代码解决方案。大多数 SO 用户会要求您证明您已经为自己解决问题付出了一些努力。此外,它可以帮助您更轻松地解决问题。祝你好运,欢迎来到 Stackoverflow。
  • 欢迎来到 SO。对于开始使用 DM 脚本作为数据分析工具,这是一个非常好的问题,因此我提供了一个比必要的更广泛的答案以供人们参考。 quick 的答案是:Volume 菜单的所有功能都可以使用我的答案底部所述的命令 SliceN 轻松重现,只需很少的代码行。
  • 你有一个可爱的用户形象;c)

标签: indexing extraction dm-script


【解决方案1】:

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

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


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

图像数据中的单个像素位置 (img) 可以被处理 使用符号

  • img[ X, 0 ] ... 用于位置 X 的一维数据
  • img[ X, Y ] ... 用于位置 X/Y 的二维数据
  • img[ X, Y, Z ] ... 用于位置 X/Y/Z 的 3D 数据

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

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

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

您可以在此表示法中使用任意大小的表达式,如XYZ,只要它们都是表达式 em>相同大小。生成的寻址数据具有此大小,并通过相应坐标引用值。

通过下面的示例,这将变得更加清晰。从一个简单的 1D 示例开始:

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) 只是使用 icol 表达式从 1000 到 1099 的线性图,该表达式在每个像素处表示该像素的 X 坐标。

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

“魔法”发生在subImg。我们使用带有coord 图像的表达式作为X 坐标。该图像的大小为 10(x1),因此输出表达式的大小为 10(x1),我们在显示之前将其分配给图像subImg

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

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()

不幸的是,它到此结束。

您不能再在 4D 或 5D 数据中执行这种类型的寻址,因为具有 4 个参数的表达式已经定义为将 2D 数据中的矩形区域寻址为img[T,L,B,R]



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

可以使用命令SliceN 及其简化变体Slice1Slice2Slice3 来处理沿数据维度方向的数据子集。

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

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

要使用Slice1 命令从任何高达 3D 的数据中提取 1D 数据,您需要以下内容(-这些正是该命令使用的 7 个参数-):

  • 数据源
  • 源中的起点
  • 采样方向
  • 采样长度
  • 采样步长

除此之外,您唯一需要知道的是:

  • 起点总是定义为X,Y,Z 三元组,即使数据源只是二维或一维。
    0 用于不需要的 尺寸。
  • 方向作为维度索引给出:0 = X、1 = Y、2 = Z
  • 步长可以为负值以指示相反的方向
  • 指定的采样必须包含在源数据中。
    (您不能“外推”)

因此,提取 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

请注意,该命令再次在源数据中返回一个 表达式,您也可以使用它来设置值,只需使用 f.e.:

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


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

以下示例提取“3D 光谱图像”的“图像平面”:

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 )

以下示例“旋转”了 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  )

您可以使用这些进行各种旋转、镜像、分箱 命令。如果您想要充分的灵活性来获得任何表达式 5D 从任何源数据到 5D,那么您需要最通用的 SliceN 命令。

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

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

例如,让我们从“4D 衍射图像”数据中提取特定空间位置的“平面”,该数据在 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 )

【讨论】:

  • 您好 BmyGuest,非常感谢您提供这些有用的建议。可爱的用户图像将有助于显微镜社区的认可:) 继续这个讨论,我想进一步说明这个问题。如果有一个“大”3D 数据集,比如 256 x 256 x 64,我只想提取偶数索引切片(切片 0、2、4...62)。除了先使用 SliceN 单独提取切片然后将它们组合在一起的方法之外,还有其他有效的命令可以满足此目的吗?否则,整个过程可能会非常乏味。
  • @DMAdventurer 只需使用data3D.slice3( 0,0,0, 0,sx,1, 1,sy,1, 2,sz/2,2 ),sx,sy,sz 是 data3D 图像的大小。
  • 这真是一个棘手而聪明的方法。通过改变 z 方向的起点,我们可以对偶数或奇数索引切片进行采样,对吗?
  • 顺便说一句,是否可以对一组更指定的切片进行采样,例如切片 2、7、9、13...(有点随意)?
  • @DMAdventurer 正确,通过将其放入循环中(并求和),您可以完成分箱。 'Slice' 命令非常强大,这就是我如此喜欢它们的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-10
  • 1970-01-01
  • 2016-02-11
  • 1970-01-01
  • 2014-11-22
  • 1970-01-01
相关资源
最近更新 更多