将函数应用于3D numpy数组

时间:2014-03-15 12:57:24

标签: python arrays image-processing numpy multidimensional-array

我有一个来自Image(PIL / Pillow)对象的numpy 3D数组。

 [[178 214 235]
  [180 215 236]
  [180 215 235]
  ..., 
  [146 173 194]
  [145 172 193]
  [146 173 194]]
 ..., 
 [[126 171 203]
  [125 169 203]
  [128 171 205]
  ..., 
  [157 171 182]
  [144 167 182]
  [131 160 180]]]

图片大小约为500x500像素。我需要为每个像素应用两个函数。

  1. 将RGB转换为LAB(使用python-colormath中的函数) 此函数采用像[157, 171, 182]这样的1D数组,并返回带有LAB颜色的1D数组,例如[53.798345635, -10.358443685, 100.358443685]
  2. 使用scipy.spatial.cKDTree从自定义调色板中查找最近的颜色。
  3. 自定义调色板为kd-tree

    palette = [[0,0,0], [127,127,127], [255,255,255]] #  or [[0.,0.,0.], [50.,0.,0.], [100.,0.,0.]] for LAB color
    tree = scipy.spatial.cKDTree(palette)
    def find nearest(pixel):
        distance, result = tree.query(pixel)
        new_pixel = palette[result]
        return new_pixel
    

    有没有比使用Python迭代更快的解决方案? E.g。

    for row in array:
        for pixel in row:
            apply_fuction1(pixel) # where pixel is one dimensional array like [157 171 182]
            apply_fuction2(pixel)
    

    UPD1 我不知道我做错了什么,但是:

    python3 -mtimeit -s'import test' 'test.find_nearest()' # my variant with 2 loops and Image.putdata()
    10 loops, best of 3: 3.35 sec per loop
    python3 -mtimeit -s'import test' 'test.find_nearest_with_map()' # list comprehension with map and Image.fromarray() by traceur
    10 loops, best of 3: 3.67 sec per loop
    python3 -mtimeit -s'import test' 'test.along_axis()' # np.apply_along_axis() and Image.fromarray() by AdrienG
    10 loops, best of 3: 5.25 sec per loop
    
    def find_nearest(array=test_array):
        new_image = []
        for row in array:
            for pixel in row:
                distance, result = tree.query(pixel)
                new_pixel = palette[result]
                new_image.append(new_pixel)
        im = Image.new('RGB', (300, 200))
        im.putdata(new_image)
    
    
    def _find_nearest(pixel):
        distance, result = tree.query(pixel)
        new_pixel = palette[result]
        return new_pixel
    
    
    def along_axis(array=test_array):
        array = np.apply_along_axis(_find_nearest, 2, array)
        im = Image.fromarray(np.uint8(array))
    
    
    def find_nearest_with_map(array=test_array):
        array = [list(map(_find_nearest, row)) for row in array]
        im = Image.fromarray(np.uint8(array))
    

2 个答案:

答案 0 :(得分:6)

对不起上一个回答,

使用numpy.apply_along_axis

a = np.arange(12).reshape((4,3))
def sum(array):
    return np.sum(array)

np.apply_along_axis(sum, 1, a)
>>> array([ 3, 12, 21, 30])

答案 1 :(得分:1)

import numpy as np

# Example of an image. 2x2x3
a = np.array([ [ [1,2,3], [4,5,6] ], 
              [ [7,8,9], [10,11,12] ] ])

# Our function. This swap first and last items of 3-item array
def rgb_to_bgr (pixel):                        
    pixel[0], pixel[2] = pixel[2], pixel[0] 
    return pixel

x,y,z = a.shape[0], a.shape[1], a.shape[2]

a = a.reshape(x*y,z)
a = np.apply_along_axis(rgb_to_bgr, 1, a)
a = a.reshape(x,y,z)

print(a)