如何从数据集中任意提取特定的图像子集? [英] How to arbitrarily extract a specific subset of images from a dataset?

查看:177
本文介绍了如何从数据集中任意提取特定的图像子集?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



在DM中,音量菜单中有许多有用的功能,但不幸的是,它们无法满足我想要的效果。



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



非常感谢您的帮助。

解决方案

有两种方法可以解决这个问题,其中一种方法只适用于高达3D的数据,通常比其他,但更灵活。
正如你一直要求任意子采样,我开始使用该选项,但第二个选项更有可能为你提供你想要的东西:正交,常规子采样。



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






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




图像数据中的单个像素位置( img )可使用符号解决




  • img [X,0] ...对于位置<$ c的1D数据$ c> X

  • img [X,Y] ...对于位置<的2D数据code> X / Y

  • img [X,Y,Z] ...位于 X / Y / Z的3D数据


请注意,即使这个地址是单个数字,结果也是 1x1 1x1x1 表达式,而不是标量数字,因此你不能这样做:数字num = img [10,4]



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



<那么这与你的问题有何关系?好吧,在上面的表达式中,我们使用标量值为 X Y Z ,结果表达式的大小为 1x1 1x1x1 ,但是


你可以使用任何大小的表达式 X Y Z 在此表示法中,只要它们都是相同大小的表达式。得到的地址数据具有此大小,其值由相应的坐标引用。


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

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

img1D = 1000 + icol //求和测试数据
coord = trunc(100 * Random())//随机整数0-99
图像subImg:= img1D [coord,0]

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



这里的testdata( 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(坐标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(坐标X,4,10)
图像coordY:= RealImage(坐标Y,4,10)
图像coordZ:= RealImage( 坐标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 及其简化变量 Slice1 Slice2 Slice3


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



让我们从1D提取的简化版开始, Slice1


使用 Slice1 命令从任何数据中提取1D数据到3D你需要以下( - 这些正是命令使用的7个参数 - ):




  • 数据源

  • 来源中的起点

  • 抽样方向

  • 抽样长度

  • 抽样步骤 - 尺寸



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




  • 起点总是定义为 X,Y,Z 三元组,即使数据源是只有2D或1D。
    0 用于不需要的
    维度。

  • 方向以维度索引给出:0 = X ,1 = Y,2 = Z

  • 步长可以是负数以指示相反的方向

  • 指定的采样必须包含在源数据中。(你不能'推断')


这是一个非常简单的提取示例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 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 )对于步长为 1 的数据的所有像素( sz )。



注意,该命令再次在源数据中返回表达式,并且您也可以使用它来设置值,只需使用fe:



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






使用命令 Slice2 和<的2D和3D数据扩展code> Slice3 是直截了当的。您可以分别定义两个三个,而不是定义一个输出方向。每个都有三个数字:方向,长度,步长



以下示例提取3D的图像平面频谱图像:

 数字sx = 20 
数字sy = 20
数字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

图像旋转:= Slice3(img3D,0, 0,0,0,sx,1,2,sz,1,1,sy,1)

ShowImage(img3D)
ShowImage(旋转)







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


它的工作方式完全相同,但您需要同时指定源数据的维度和输出表达式的维度。然后,需要使用源数据维度建议的坐标来定义起始点,并且每个输出维度需要一个三元组规范。



For源数据 N 维度,并希望输出 M 您需要的维度: 2 + N + 3 * M 参数。



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

  number sx = 9 
number sy = 9
数字kx = 9
数字ky = 9

图像img4D:= RealImage(衍射图像,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)


Recently I'm planning to manipulate a stack of images and the goal is to extract a specific subset of slices from there, for example only even or odd or arbitrary indexes, and then save them into another dataset.

In DM, there are a number of helpful functions in the Volume menu but unfortunately, they cannot really fullfill what I want to do.

I am just wondering whether this idea can be realized via scripting.

Many thanks for your help in advance.

解决方案

There are two ways you can go about it, one of them only suitable for data up to 3D and generally slower than the other, but more flexible. As you have been asking for arbitrary subsampling, I'm starting with that option, but it is more likely that the second option gives you what you want: orthogonal, regular subsampling.

If you are in a hurry, the short answer is: Use the SliceN command.


1) Using expressions (arbitrary subsampling)

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

Note that even if this addresses a single number, the result is an expression of size 1x1 or 1x1x1 and not a scalar number, therefore you can not do: number num = img[10,4]

However, you can use a little trick to use any of the functions that convert an expression to a single number like f.e. summation. So you can do: number num = sum(img[10,4])

So how does this relate to your question? Well, in the expressions above, we used scalar values as X, Y and Z, and the resulting expressions were expressions of size 1x1 and 1x1x1, but

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.

This will become clearer with the examples below. Starting out with a simple 1D example:

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

Our testdata (img1D) here is just a linear graph from 1000 to 1099 using the icol expression which, at each pixel, represents that pixels X coordinate.

The coordinate image (coord) is containing random integer values between 0 and 99.

The 'magic' happens in the subImg. We use an expression with the coord image as X coordinates. That images is of size 10(x1), so the outcoming expression is of size 10(x1) which we assign to the image subImg before showing it.

Note, that the expression we have built is really just pointing to that data of the image. Instead of showing it as a new image, we could have use that expression to change these points in the data instead, using:

img1D[coord,0] = 0


Taking it from here, it is straight forward to extend the example to 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()


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


Unfortunately, it ends here.

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) Using SliceN (orthogonal subsampling)

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

The SliceN command is maybe one of my favourite commands in the language when dealing with data. It looks intimidating at first, but it is straight forward.

Lets start with its simplified version for 1D extraction, 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')

So a very simple example of extracting a 1D data of a 3D dataset would be:

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 )

This example showed a quite typical situation in analytical microscopy when dealing with "3D Spectrum Image" data: Extracting a "1D Spectrum" at a specific spatial position.

The example did that for the spatial point px,py. Starting at the point at that position (px,py,0), it samples along the Z direction (2) for all pixels of the data (sz) with a step-size of 1.

Note, that the command again returns an expression within the source data, and that you can use this to set values as well, just using f.e.:

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


The extension for 2D and 3D data using the commands Slice2 and Slice3 is straight forward. Instead of defining one output direction, you define two or three, respectively. Each with a triplet of numbers: direction, length, step-size.

The following example extracts an "image plane" of a "3D Spectrum image":

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 )

And the following example "rotates" a 3D image:

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.

It works exactly the same, but you need to specify both the dimensionality of the source data, and the dimensionality of the output expression. Then, the 'starting' point needs to be defined with as many coordinates as the source data dimension suggests, and you need one triplet of specification for each output dimension.

For a source data of N dimensions and want an output of M dimensions you need: 2 + N + 3*M parameters.

As an example, lets extract the "plane" at specific spatial position from a "4D Diffraction image" data, which stores a 2D image at each spatial location of a 2D scan:

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 )

这篇关于如何从数据集中任意提取特定的图像子集?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆