将numpy阵列的每个元素乘以元组



给定一个具有形状(height, width, 3)的2D numpy图像阵列,而BGR元组作为元素,我想将每个元素乘以一个内核来单独提取B/G/R通道。例如,蓝色内核将是(1, 0, 0)。这样的东西:

# extact color channel
def extract_color_channel(image, kernel):
   channel = np.copy(image)
   height, width = image.shape[:2]
   for y in range(0, height):
      for x in range(0, width):
         channel[y,x] = image[y, x] * kernel
   return channel
# extract blue channel
def extract_blue(image):
   return extract_color_channel(image, (1, 0, 0))

这样做的最有效的" numpy方法"是什么?

带有样本数组:

In [220]: arr = np.arange(5*5*3).reshape(5,5,3)

基本索引是最有效的方法(这将是view

In [221]: arr[:,:,0]
Out[221]: 
array([[ 0,  3,  6,  9, 12],
       [15, 18, 21, 24, 27],
       [30, 33, 36, 39, 42],
       [45, 48, 51, 54, 57],
       [60, 63, 66, 69, 72]])

[1,0,0]列表不是您想要的。但是您可以将其作为Bool阵列。

In [222]: kernel = np.array([1,0,0],dtype=bool)
In [223]: kernel
Out[223]: array([ True, False, False], dtype=bool)
In [224]: arr[:,:,kernel].shape
Out[224]: (5, 5, 1)
In [225]: arr[:,:,kernel].squeeze()
Out[225]: 
array([[ 0,  3,  6,  9, 12],
       [15, 18, 21, 24, 27],
       [30, 33, 36, 39, 42],
       [45, 48, 51, 54, 57],
       [60, 63, 66, 69, 72]])

请注意,布尔值的形状仍然是3D。如果您不想要那个,那么您需要重塑或挤出最后的尺寸。此索引较慢,因为它使copy

此布尔索引等效于

In [226]: arr[:,:,[0]].shape
Out[226]: (5, 5, 1)

其中 [0]kernel中的" true"值的位置。

您也可以使用dot(矩阵产品):

In [228]: np.dot(arr,[1,0,0])
Out[228]: 
array([[ 0,  3,  6,  9, 12],
       [15, 18, 21, 24, 27],
       [30, 33, 36, 39, 42],
       [45, 48, 51, 54, 57],
       [60, 63, 66, 69, 72]])

它比索引要慢。

元素乘法:

在[232]中:arr*np.array([1,0,0])出去[232]:阵列([[[[0,0,0], [3,0,0], [6,0,0], [9,0,0], [12,0,0]],

   [[15,  0,  0],
    [18,  0,  0],
       ....
    [66,  0,  0],
    [69,  0,  0],
    [72,  0,  0]]])

在此乘法中,[1,0,0]的行为似乎是(1,1,3)数组,并且用(n,n,3)播放(n,n,3)恰好。

最新更新