广播到 Numpy 数组的视图中

Posted

技术标签:

【中文标题】广播到 Numpy 数组的视图中【英文标题】:Broadcasting into views of Numpy arrays 【发布时间】:2015-02-20 03:21:57 【问题描述】:

我正在通过 numpy 处理图像。我想将图像的一大块设置为其平均颜色。我能够做到这一点,但是当我想使用原始视图来执行此操作时,我必须重新索引数组。换句话说,我想使用第 4 行代码,但我坚持使用第 3 行。

我已经阅读了一些关于 as_strided 函数的帖子,但这让我感到困惑,我希望可能有一个更简单的解决方案。那么有没有办法稍微修改最后一行代码来做我想做的事?

box = im[x-dx:x+dx, y-dy:y+dy, :]
avg = block(box) #returns a 1D numpy array with 3 values
im[x-dx:x+dx, y-dy:y+dy, :] = avg[None,None,:] #sets box to average color
#box = avg[None,None,:] #does not affect original array

【问题讨论】:

【参考方案1】:
box = blah

只需重新分配 box 变量。 box 变量之前引用的数组不受影响。这不是你想要的。

box[:] = blah

是一个切片赋值。它修改数组的内容。这就是你想要的。

请注意,切片分配取决于语句的句法形式。 boxbox = im[stuff] 分配的事实不会对box 切片分配进行进一步分配。这类似于如果你这样做

l = [1, 2, 3]
b = l[2]
b = 0

分配给b 不会影响l

【讨论】:

太棒了,正是我需要的。【参考方案2】:

灰度图像

这会将数组的一部分设置为其平均(平均值)值:

im[2:4, 2:4] = im[2:4, 2:4].mean()

例如:

In [9]: im
Out[9]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 10, 11],
       [12, 13, 14, 15]])

In [10]: im[2:4, 2:4] = im[2:4, 2:4].mean()

In [11]: im
Out[11]: 
array([[ 0,  1,  2,  3],
       [ 4,  5,  6,  7],
       [ 8,  9, 12, 12],
       [12, 13, 12, 12]])

彩色图片

假设我们要分别对颜色的每个分量进行平均:

In [22]: im = np.arange(48).reshape((4,4,3))

In [23]: im
Out[23]: 
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11]],

       [[12, 13, 14],
        [15, 16, 17],
        [18, 19, 20],
        [21, 22, 23]],

       [[24, 25, 26],
        [27, 28, 29],
        [30, 31, 32],
        [33, 34, 35]],

       [[36, 37, 38],
        [39, 40, 41],
        [42, 43, 44],
        [45, 46, 47]]])

In [24]: im[2:4, 2:4, :] = im[2:4, 2:4, :].mean(axis=0).mean(axis=0)[np.newaxis, np.newaxis, :]

In [25]: im
Out[25]: 
array([[[ 0,  1,  2],
        [ 3,  4,  5],
        [ 6,  7,  8],
        [ 9, 10, 11]],

       [[12, 13, 14],
        [15, 16, 17],
        [18, 19, 20],
        [21, 22, 23]],

       [[24, 25, 26],
        [27, 28, 29],
        [37, 38, 39],
        [37, 38, 39]],

       [[36, 37, 38],
        [39, 40, 41],
        [37, 38, 39],
        [37, 38, 39]]])

【讨论】:

嗯,这绝对看起来比我的代码更像 Numpy。我只是在 for 循环中使用了sp.average(box[...,i]),将其附加到列表中,然后将其转换为数组。

以上是关于广播到 Numpy 数组的视图中的主要内容,如果未能解决你的问题,请参考以下文章

numpy:数组的运算与广播机制

numpy 广播

Numpy中的广播(Broadcasting)

numpy数组广播

关于Numpy中+=与-=操作符不支持数组广播的特性

初探numpy——广播和数组操作函数