【问题标题】:Crop different portions of image from 4D array for data augmentation从 4D 数组中裁剪图像的不同部分以进行数据增强
【发布时间】:2018-07-02 17:36:25
【问题描述】:

我有以下批处理的 RGB 图像数组(4D 数组):

In [55]: img_arr = np.random.randint(0, 255, (10000, 32, 32, 3))

现在,我只想从左上角跨所有3 通道裁剪某些维度,比如(12x12),最好还沿着批处理维度(即axis 0)裁剪,全部合二为一走。我的想法是制作一个网格并对其进行切片。所以,我构建了这个网格:

In [56]: grid = np.c_[np.arange(12)]+ np.r_[np.arange(12)]

In [57]: grid.shape
Out[57]: (12, 12)

但是,当我对数组进行切片时,我得到了一些意想不到的东西:

In [58]: img_arr[:, grid, :].shape
Out[58]: (10000, 12, 12, 32, 3)

我期望并且需要结果是 (10000, 12, 12, 3) 的形状,但我不知道 32 的来源。

这只是一个例子。理想情况下,我想在图像上的 10 个不同位置进行裁剪,即。左上、右上、左下、右下等,

但是,首先进行左上角裁剪,其余的应该是直观的。

此外,如您所见,我需要在单个 4D 数组中沿批量维度存储超过 100K 的图像,因此在进行此类随机裁剪时拥有 视图 会非常好,因为它会节省内存。

【问题讨论】:

  • 您打算如何在数学上介绍这 10 个职位?也许(x,y) 每个补丁的开始(左上角点)?
  • @Divakar 每个原始图像裁剪部分位于:top-left, top-right, bottom-left, bottom-right, center crop;然后,水平翻转图像并再次裁剪:top-left, top-right, bottom-left, bottom-right, and center crop。数据增强:)
  • 是的,然后按照发布的答案中的建议对其进行切片。对于水平翻转,使用a[:,::-1] 并使用相同的切片,即a[:,::-1][:,:12,:12,:] 等等。对于垂直翻转:a[:,:,::-1].
  • @Divakar 哦,太酷了!因此,我们只需拥有一份原始数组即可实现一切。您想将其添加为答案吗?
  • 希望您添加一些来源(文档)并将其添加为答案:)

标签: python numpy image-processing multidimensional-array computer-vision


【解决方案1】:

我们可以为此使用slicing:我们可以指定第二维和第三维的范围,例如:

sub_img = img_arr[:, <b>:12, :12</b> , :]

然后sub_img.shape == (10000, 12, 12, 3)。因此,在这里我们指定了012 的范围(但我们不需要明确声明0)。我们对第二维和第三维执行此操作。它也非常具有声明性:我们构造一个sub_img,其中第一个索引取所有(:),第二个索引到第十二个(:12),等等。

注意我们不需要指定tailing:s,也可以这样写:

sub_img = img_arr[:, :12, :12]  # no last ":"

切片作为视图

注意我们这里构造一个视图,我们复制数组,我们只构造一个视图。因此,如果我们在视图范围内对img_arr 进行更改,我们将能够在sub_img 中看到,反之亦然。如果您需要副本,您可以通过 array 构造函数传递例如视图:

sub_img = <b>np.array(</b>img_arr[:, :12, :12]<b>)</b>  # making a copy, instead of a view

但是使用视图可能是有益的,因为它几乎不使用内存来存储视图(这里大约 144 字节,而副本大约需要 34 兆字节),而且视图的构建几乎是即时的(通常它可以缩放维数),而副本将随元素数缩放。

使用slice对象的任意维数

如果维数是任意的,我们也可以传递slice 对象的元组。

例如第一个表达式等价于:

# equivalent to the first code fragment
indices = (slice(None), slice(12), slice(12))
sub_img = img_arr[indices]

所以如果维数是任意的,我们可以先构造这样的元组。一个将除第一个和最后一个维度之外的所有维度分割为 12 的元组例如:

# generalized with arbitrary number of dimensions
indices = (slice(None), *(slice(12) for _ in range(img_arr.ndim - 2)))
sub_img = img_arr[indices]

【讨论】:

  • 非常好!所以,我只需要硬编码尺寸和img_arr 中我想使用切片索引裁剪的位置。
  • @kmario23:你确实不必必须硬编码,你也可以使用像a = 12这样的标识符,然后是sub_img = img_arr[:, :a, :a]。您甚至不必对维数进行硬编码,您可以传递带有切片的元组。
猜你喜欢
  • 1970-01-01
  • 2021-11-09
  • 2014-04-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多