【问题标题】:Applying a mapping function to each member of an ndarray with indices as arguments将映射函数应用于以索引为参数的 ndarray 的每个成员
【发布时间】:2019-05-18 00:51:00
【问题描述】:

我有一个代表 RGB 图像的 ndarray,形状为 (width,height,3),我希望将每个值替换为它自身的某个函数、它的位置和它所属的颜色通道的结果。在三个嵌套的 for 循环中这样做非常慢,有没有办法将其表示为原生数组操作?

编辑:寻找一个就地解决方案 - 一个不涉及创建另一个 O(width x height) ndarray 的解决方案(除非 numpy 有一些魔法可以防止这样的 ndarray 实际被分配)

【问题讨论】:

  • 取决于您要应用的具体功能。你能说得更具体点吗?
  • 很多函数可以直接应用在数组上。您还可以使用np.indices(your_array.shape) 来获取图像的索引值。你想应用什么功能?
  • 理想情况下,我想应用任何可调用 python 的结果,但假设我想将每个通道乘以一个(不同的)常数乘以它与中心的(标准化)距离。
  • 如果您的函数一次只能处理一个元素(在宽度/高度空间中),则需要某种 Python 级别的迭代。大多数快速编译的numpy 操作在数学上都是简单的(例如乘法),它们采用整个数组并返回一个新数组。只要您的问题仍然笼统,答案就会笼统。
  • 您为什么担心分配新的(或临时的)数组?你认为这会使计算更快吗?我感觉您需要更多的基本 numpy 计算经验,更好地了解快慢方式。

标签: python numpy numpy-ndarray


【解决方案1】:

注意许多 cmets 中的限定条件,直接使用 numpy 算术通常会更容易和更快。

import numpy as np

def test(item, ix0, ix1, ix2):
    # A function with the required signature. This you customise to suit.
    return item*(ix0+ix1+ix2)//202

def make_function_for(arr, f):
''' where arr is a 3D numpy array and f is a function taking four arguments.
        item : the item from the array
        ix0 ... ix2 : the three indices
    it returns the required result from these 4 arguments. 
'''
    def user_f(ix0, ix1, ix2):
        # np.fromfunction requires only the three indices as arguments.
        ix0=ix0.astype(np.int32)
        ix1=ix1.astype(np.int32)
        ix2=ix2.astype(np.int32)
        return f(arr[ix0, ix1, ix2], ix0, ix1, ix2)
    return user_f
    # user_f is a function suitable for calling in np.fromfunction

a=np.arange(100*100*3)
a.shape=100,100,3
a[...]=np.fromfunction(make_function_for(a, test), a.shape)

我的测试函数非常简单,所以我可以在 numpy 中完成。

使用from函数:

%timeit np.fromfunction(make_function_for(a, test), a.shape)
5.7 ms ± 346 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

使用 numpy 算术:

def alt_func(arr):
    temp=np.add.outer(np.arange(arr.shape[0]), np.arange(arr.shape[1]))
    temp=np.add.outer(temp,np.arange(arr.shape[2]))
    return arr*temp//202

%timeit alt_func(a)
967 µs ± 4.94 µs per loop  (mean ± std. dev. of 7 runs, 1000 loops each)

因此,在这种情况下,我的机器上的 numpy 算术几乎快 6 倍。

已编辑以纠正我看似不可避免的错别字!

【讨论】:

    【解决方案2】:

    我不确定你的问题是否正确!我的理解是,您希望根据相应的索引在 RGB 图像的每个通道上应用映射,如果是这样,MIGHT 下面的代码会有所帮助,因为您的问题中没有详细信息。

    import numpy as np
    
    bit_depth = 8
    patch_size = 32    
    
    def lut_generator(constant_multiplier):
        x = np.arange(2 ** bit_depth)
        y = constant_multiplier * x
        return dict(zip(x, y))
    
    
    rgb = np.random.randint(0, (2**bit_depth), (patch_size, patch_size, 3))
    # Considering a simple lookup table without using indices.
    lut = lut_generator(5)
    
    # splitting three channels followed and their respective indices.
    # You can use indexes wherever you need them.
    r, g, b = np.dsplit(rgb, rgb.shape[-1])
    indexes = np.arange(rgb.size).reshape(rgb.shape)
    r_idx, g_idx, b_idx = np.dsplit(indexes, indexes.shape[-1])
    
    # Apply transformation on each channel.
    transformed_r = np.vectorize(lut.get)(r)
    transformed_g = np.vectorize(lut.get)(g)
    transformed_b = np.vectorize(lut.get)(b)
    

    祝你好运!

    【讨论】:

      猜你喜欢
      • 2023-03-05
      • 2014-04-30
      • 1970-01-01
      • 2015-12-15
      • 1970-01-01
      • 2014-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多