掩蔽图像中红色和蓝色通道的矢量化方法

Vectorized approach to masking red and blue channels in an image

我正在尝试将图像中的所有红色和蓝色像素更改为黑色以仅包含绿色像素(基于特定条件)。

现在为了做到这一点,我使用了多个 for 循环,这个过程虽然有效,但速度非常慢。

我目前的代码 -

### Test image is my original RGB image
mat = np.asarray(testim)

for elemento in mat: 

    for pixel in element:

        if ((pixel[0] + pixel[2]) >= (2*pixel[1])): #Non-vegetation background changing to black according to the rule (R + B >= 2G)
          pixel[0] = 0
          pixel[1] = 0
          pixel[2] = 0
        
        elif pixel[1] > pixel[0] and pixel[1] > pixel[2] and pixel[1] > 25: # Treat these as green vegetation and do not change anything
          continue
        
        else: # Change background to black
          pixel[0] = 0
          pixel[1] = 0
          pixel[2] = 0
cv2_imshow(testim)
print(testim.shape)

有没有什么方法可以使用 Numpy 对其进行矢量化而不使用嵌套的 for 循环来使相同的过程更快地运行?我对 NumPy 操作有点陌生,对如何完成它感到困惑。感谢您的帮助!

例如: 我的输入图像 - [1]: https://i.stack.imgur.com/zWGtA.jpg

我现在用上述逻辑得到的输出图像 - [2]: https://i.stack.imgur.com/VkmLC.jpg

我希望使用更快的代码获得相同的输出,最好使用 NumPy 而不是我目前拥有的嵌套 for 循环

您应该可以使用 mat[:,:,0] 访问红色矩阵,使用绿色和蓝色也类似。

你的绿色像素蒙版是:

mask = (mat[:,:,1]>mat[:,:,0]) & (mat[:,:,1]>mat[:,:,2]) & (mat[:,:,1]>25)

您在其中进行逐元素比较和逐元素 AND 以在布尔二维矩阵中组合比较。

然后您可以通过执行以下操作将彼此的像素归零:

# Repeat mask along the three channels
mask = np.repeat(mask[:,:,np.newaxis], 3, axis=2)

# Zero non-green elements
mat[~mask] = 0

根据您的代码,当

时您没有更改值
pixel[1] > pixel[0] and pixel[1] > pixel[2] and pixel[1] > 25

所以我们可以形成这个条件的布尔数组,并将其倒数索引到数组中并将这些位置设置为 0:

# since used more than once, assign to a variable
green = mat[:, :, 1]

# your "elif" condition
not_change_condition = (green > mat[:, :, 0]) & (green > mat[:, :, 2]) & (green > 25)

# index with its inverse and change
mat[~not_change_condition] = 0

我将图像数组拆分为三个数组(r, g, b),使规则更直观。使用这种格式添加任何新的应该很容易!

r, g, b = mat[:,:,0], mat[:,:,1], mat[:,:,2]
rule_1 = (r + b > 2 * g)
rule_2 = ~((g > r) & (g > b) & (g > 25))
mat[rule_1 | rule_2] = 0