簡體   English   中英

如何刪除 numpy 減去 2d 和 3d arrays 的循環?

[英]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)

減去 colors 的注意事項

當通過取單個 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM