Python 如何选择NumPy阵列中的所有非黑色像素?

Python 如何选择NumPy阵列中的所有非黑色像素?,python,image,numpy,image-processing,Python,Image,Numpy,Image Processing,我正在尝试使用NumPy获取与特定颜色不同的图像像素列表 例如,在处理以下图像时: 我已通过以下方式获得了所有黑色像素的列表: np.where(np.all(mask == [0,0,0], axis=-1)) 但当我尝试这样做时: np.where(np.all(mask != [0,0,0], axis=-1)) 我得到了一个非常奇怪的结果: 看起来NumPy只返回了索引R、G和B为非0的索引 下面是我尝试做的一个简单示例: import numpy as np import cv2

我正在尝试使用NumPy获取与特定颜色不同的图像像素列表

例如,在处理以下图像时:

我已通过以下方式获得了所有黑色像素的列表:

np.where(np.all(mask == [0,0,0], axis=-1))
但当我尝试这样做时:

np.where(np.all(mask != [0,0,0], axis=-1))
我得到了一个非常奇怪的结果:

看起来NumPy只返回了索引R、G和B为非0的索引

下面是我尝试做的一个简单示例:

import numpy as np
import cv2

# Read mask
mask = cv2.imread("path/to/img")
excluded_color = [0,0,0]

# Try to get indices of pixel with different colors
indices_list = np.where(np.all(mask != excluded_color, axis=-1))

# For some reason, the list doesn't contain all different colors
print("excluded indices are", indices_list)

# Visualization
mask[indices_list] = [255,255,255]

cv2.imshow(mask)
cv2.waitKey(0)

必要性:需要此形状的矩阵=任意,任意,3

解决方案:

解决方案2:

获取特定颜色的间隔,例如红色:

COLOR1 = [250,0,0]
COLOR2 = [260,0,0] # doesnt matter its over limit

indices1 = np.where(np.all(mask >= COLOR1, axis=-1))
indexes1 = zip(indices[0], indices[1])

indices2 = np.where(np.all(mask <= COLOR2, axis=-1))
indexes2 = zip(indices[0], indices[1])

# You now want indexes that are in both indexes1 and indexes2
解决方案3-证明有效

如果以前的解决方案不起作用,那么有一个解决方案可以100%起作用

从RGB频道转换到HSV。从3D图像制作2D遮罩。2D遮罩将包含色调值。比较色调比RGB更容易,因为色调是1值,而RGB是3值的向量。创建具有色调值的2D矩阵后,请执行上述操作:

HUE1 = 0.5
HUE2 = 0.7 

indices1 = np.where(HUEmask >= HUE1)
indexes1 = zip(indices[0], indices[1])

indices2 = np.where(HUEmask <= HUE2)
indexes2 = zip(indices[0], indices[1])
您可以对饱和度和值执行相同的操作。

在第二种情况下,选择除黑色像素以外的所有像素时,您应该使用而不是:

np.any(image != [0, 0, 0], axis=-1)
或者简单地通过以下方式反转布尔数组来获得黑色像素的补码:

工作示例:


如果有人使用matplotlib打印结果并得到完全黑色的图像或警告,请参阅此帖子:

有关选择非黑色像素的特殊情况,在查找非零像素之前将图像转换为灰度会更快:

non_black_indices = np.nonzero(cv2.cvtColor(img,cv2.COLOR_BGR2GRAY))
然后将所有黑色像素更改为白色,例如:

img[non_black_indices] = [255,255,255]

同样,这只适用于选择非[0,0,0]像素,但如果你正在处理数千张图像,与更一般的方法相比,速度提升变得非常显著。

我仍然不清楚为什么它应该是np.any而不是np.all。我会考虑更多,并尝试提供解释。但是无论如何,我更喜欢使用~。谢谢你的回答,我想我现在明白了为什么np.any是必要的。当我使用np.all时发生的事情是数组只包含带有R的颜色=0和B=0和G=0这意味着颜色[255,0,0]会导致错误。通过使用np.any,条件变为R=0或B=0或G=0
import numpy as np
import matplotlib.pyplot as plt


image = plt.imread('example.png')
plt.imshow(image)
plt.show()
image_copy = image.copy()

black_pixels_mask = np.all(image == [0, 0, 0], axis=-1)

non_black_pixels_mask = np.any(image != [0, 0, 0], axis=-1)  
# or non_black_pixels_mask = ~black_pixels_mask

image_copy[black_pixels_mask] = [255, 255, 255]
image_copy[non_black_pixels_mask] = [0, 0, 0]

plt.imshow(image_copy)
plt.show()
non_black_indices = np.nonzero(cv2.cvtColor(img,cv2.COLOR_BGR2GRAY))
img[non_black_indices] = [255,255,255]