【问题标题】:Set a numpy slice using np.where based on another dimension使用 np.where 基于另一个维度设置一个 numpy 切片
【发布时间】:2019-03-06 23:34:20
【问题描述】:

如何根据第 4 通道中的值设置 4 通道 numpy 数组的前 3 个通道中的值?是否可以使用 numpy 切片作为左值来做到这一点?

给定一个具有 4 个通道的 3 x 2 像素 numpy 数组

a = np.arange(24).reshape(3,2,4)
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]]])

我可以选择第 4 通道为模 3 的切片。

px = np.where(0==a[:,:,3]%3)
(array([0, 1], dtype=int64), array([0, 1], dtype=int64))

a[px]
array([[ 0,  1,  2,  3],
       [12, 13, 14, 15]])

现在我想将 a 中这些行中的前 3 个通道设置为 0,以便结果如下所示:

a
array([[[ 0,  0,  0,  3],
        [ 4,  5,  6,  7]],
       [[ 8,  9, 10, 11],
        [ 0,  0,  0, 15]],
       [[16, 17, 18, 19],
        [20, 21, 22, 23]]])

我试过了

a[px][:,0:3] = 0

但这会使数组保持不变。

我阅读了Setting values in a numpy arrays indexed by a slice and two boolean arrays,但不明白如何使用布尔索引仅设置前 3 个频道。

【问题讨论】:

    标签: python numpy opencv


    【解决方案1】:

    这是一种方法:

    >>> px0, px1 = np.where(0==a[:,:,3]%3)
    >>> a[px0, px1, :3] = 0
    >>> a
    array([[[ 0,  0,  0,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [ 0,  0,  0, 15]],
    
           [[16, 17, 18, 19],
            [20, 21, 22, 23]]])
    

    >>> px = np.where(0==a[:,:,3]%3)
    >>> a[..., :3][px] = 0
    >>> a
    array([[[ 0,  0,  0,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [ 0,  0,  0, 15]],
    
           [[16, 17, 18, 19],
            [20, 21, 22, 23]]])
    

    >>> a[(*px, np.s_[:3])] = 0
    >>> a
    array([[[ 0,  0,  0,  3],
            [ 4,  5,  6,  7]],
    
           [[ 8,  9, 10, 11],
            [ 0,  0,  0, 15]],
    
           [[16, 17, 18, 19],
            [20, 21, 22, 23]]])
    

    【讨论】:

    • 谢谢。你一定是个麻木的神。是的。 a[px[0],px[1],:3] = 0a[:,:,:3][px] = 0a[(px[0], px[1], np.s_[:3])] = 0 也可以。 Ellipsis syntax 和使用 s_ slice syntax 解包到一个元组非常酷。为什么a[px][:,0:3] = 0 不起作用?我缺少什么原则?
    • 这有点棘手。 a[px] = 0a.__setitem__(px, 0) 的语法糖,所以可以正常工作。 a[px][:, :3] = 0a.__getitem__(px).__setitem__((slice(None), slice(3)), 0)。正如px 指示精美的索引,__getitem__ 复制引用的数据。随着后续__setitem__ 写入此副本,a 不会被修改。如果我们先做[..., :3],然后再做[px],它看起来很相似,但有一个关键区别。 __getitem__ 的 arg 是一个切片,因此它将一个视图返回到 a 的原始数据缓冲区中。所以__setitem__通过自动写入这个视图也会影响a
    猜你喜欢
    • 1970-01-01
    • 2016-06-30
    • 1970-01-01
    • 1970-01-01
    • 2012-09-17
    • 2021-06-27
    • 1970-01-01
    • 1970-01-01
    • 2017-07-06
    相关资源
    最近更新 更多