[英]How do I remove loop for numpy subtraction of 2d and 3d arrays?
是否可以通過刪除 for 循環來加速以下代碼?
all_t = np.array([])
for color in color_list:
t = np.subtract(image, color)
all_t = np.append(all_t, t)
all_t = all_t.reshape(len(color_list), image.shape[0], image.shape[1])
我如何使用代碼:
color_list
是一個形狀為 (z,3) 的 numpy 數組。 它由具有 RGB 值的 z colors 組成image
是一個形狀為 (x,y,3) 的 numpy 數組。 它是尺寸為 (x,y) 的 RGB 圖像all_t
是一個形狀為 (z,x,y) 的 numpy 數組,由減去顏色值的 z 圖像組成編輯:
all_t
的形狀為 (z,x,y,3)all_t = all_t.reshape(len(color_list), image.shape[0], image.shape[1], 3)
添加
另一種方法,也是通過理解列表,其中為列表中的每種顏色制作一個掩碼,然后執行一次減法
color_map = np.array([[[color_list[i]] * image.shape[0]] * image.shape[1] for i in range(len(color_list))])
images = [image] * len(color_list)
all_t = np.subtract(images,color_map)
您可以將性能與相關代碼進行比較,結果將取決於 color_list 的長度和圖像大小。
Previouse Assumption Temporary,如果我們使用您的代碼的列表理解版本:
all_t = [np.subtract(image,color) for color in color_list]
all_t = np.array(all_t)
all_t = all_t.reshape(len(color_list), image.shape[0], image.shape[1]
這是從代碼中刪除 for 循環的解決方案。 我將使用您減去兩個像素的方法(這可能導致無效的像素值)請參閱下面的替代解決方案
您有兩個 numpy arrays:形狀image
(x, y, 3)
color_list
of shape (z, 3)
您的目標是從image
中減去color_list
中的每種顏色,從而產生z
個不同的圖像,這些圖像可以存儲在形狀數組(z, x, y, 3)
# First we repeat the pixel values according to the number of colors we would like to subtract ie. `len(color_list) = z`
# The shape of rep_images will be(x, y, z, 3)
rep_images = np.repeat(image[:,:,None], len(color_list), axis=2)
# We can no subtract `color_list` from `rep_images`.
# This results in the first color being subtracted from the pixels along `z` at index 0, second color form pixels along `z` index 1 etc.
sub_image = rep_images - color_list
# Now we can move the `z` axis to the front in order to have `z` images, of `x` by `y` pixels of 3 RGB colors
# `result` now has a shape of (z, x, y, 3) and contains the z subtracted images
result = np.moveaxis(sub_image, 2, 0)
當通過取單個 R、G 和 B 通道的差異以微不足道的方式減去 colors 時,您可以輕松得出無效的 colors。
例如,從 (0, 0, 0) 中減去(255, 0, 0)
(0, 0, 0)
將得到(-255, 0,0)
天真的方法是將負值設置為零:
result[result < 0] = 0
然而,可以采用其他方法。 例如:
這些方法中的大多數可以通過將圖像和 colors 轉換為 HSL 並使用相同的算法來使用。 以下是一些有用的資源:
In [189]: color_list = np.array([[1,2,3],[4,5,6]])
In [190]: color_list.shape
Out[190]: (2, 3)
In [191]: image = np.ones((4,5,3),int)
In [192]: all_t = np.array([])
...: for color in color_list:
...: t = np.subtract(image, color)
...: all_t = np.append(all_t, t)
...:
In [193]: all_t.shape
Out[193]: (120,)
all_t
是一維數組。 np.append
很清楚,沒有axis
它會使所有輸入變平/散開。
您的重塑是錯誤的,忽略了 3 尺寸:
In [194]: all_t.reshape(len(color_list), image.shape[0], image.shape[1])
Traceback (most recent call last):
File "<ipython-input-194-c246f37a52d0>", line 1, in <module>
all_t.reshape(len(color_list), image.shape[0], image.shape[1])
ValueError: cannot reshape array of size 120 into shape (2,4,5)
工作重塑:
In [195]: x=all_t.reshape(len(color_list), image.shape[0], image.shape[1],3)
In [196]: x.shape
Out[196]: (2, 4, 5, 3)
如果要迭代構建一個數組,請使用列表 append。 它更快,更容易正確使用:
In [197]: all_t = []
...: for color in color_list:
...: t = np.subtract(image, color)
...: all_t.append(t)
...:
In [198]: len(all_t)
Out[198]: 2
In [199]: y = np.array(all_t)
In [200]: y.shape
Out[200]: (2, 4, 5, 3)
In [201]: np.allclose(x,y)
Out[201]: True
但是沒有必要迭代color_list
的第一個維度:
In [202]: z = image - color_list[:,None,None,:]
In [203]: z.shape
Out[203]: (2, 4, 5, 3)
In [204]: np.allclose(x,z)
Out[204]: True
通過廣播規則這是
(4,5,3) array - a (2,1,1,3)
(1,4,5,3)
(2,4,5,3)
另一個答案https://stackoverflow.com/a/65550381/901925構造:
In [205]: np.repeat(image[:,:,None], len(color_list), axis=2).shape
Out[205]: (4, 5, 2, 3)
In [206]: color_list.shape
Out[206]: (2, 3)
通過廣播也可以工作(206 擴展到 (1,1,2,3)); 然后他更改維度順序。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.