Python 将numpy数组的每个元素乘以一个元组

Python 将numpy数组的每个元素乘以一个元组,python,arrays,numpy,multidimensional-array,Python,Arrays,Numpy,Multidimensional Array,给定一个二维numpy图像数组,其中shape(height,width,3),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,

给定一个二维numpy图像数组,其中shape
(height,width,3)
,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)
基本索引是最有效的方法(这将是一个
视图

[1,0,0]
列表不是您想要的。但是你可以把它变成布尔数组

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]])
请注意,带有布尔值的形状仍然是三维的。如果你不想这样,那么你需要重塑或挤出最后的尺寸。此索引速度较慢,因为它会生成
副本

此布尔索引相当于

In [226]: arr[:,:,[0]].shape
Out[226]: (5, 5, 1)
其中
[0]
内核中“true”值的位置

您也可以使用
(矩阵积):

它将比索引速度慢

元素乘法:

[232]中:arr*np.数组([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)进行广播很好。

为什么不只是
image[:,:,0]
?我对numpy是新手,你能解释一下/给我指出
0
的解释吗?为什么不
image[:,:,:,kernel]
?阅读numpy文档…这是完全基本的!这是基本索引,意味着您要从数组中提取一个切片,然后指定相应的索引。请参见此处。好的,我看到了此处发生的情况。在图像上下文中,
图像[:,:,0]
丢弃红色和绿色通道,并从蓝色通道生成灰度图像。有没有办法不丢弃这些通道,而将它们设置为0?因此,如果我输出图像,它仍然以彩色显示?而不是使用
图像[:,:,0]切片蓝色通道
,我只是将1和2个通道归零?这很有帮助,但我遗漏了一些东西。如果在我的示例数组中,我改为:
arr=np.ones([5,5,3])*255,设置每个“像素”白色。我想要的是运行
extract\u blues
获得一个平坦的蓝色图像,
extract\u reds
获得一个平坦的红色图像,等等。我不想更改数组的形状。在我的示例中,每个值
arr[y,x]
产生
(255,255)
。在
extract\u blues
之后,每个值
arr[y,x]
应该生成
(255,0,0)
。很抱歉,我可能在与
[:,:,0]
进行比较时偏离了轨道。请确定您可以将(n,n,3)乘以(3,).他们一起广播。其他数学也很有用。
就是这样的乘法加和。我专注于“提取”,而不是修改或构建新图像。是的,单词选择:/。无论如何,这让我走上了正确的轨道。还有“提取”不管怎样,从长远来看,灰度化可能是我想要做的。接受这个,谢谢你的帮助。
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]])
   [[15,  0,  0],
    [18,  0,  0],
       ....
    [66,  0,  0],
    [69,  0,  0],
    [72,  0,  0]]])