【问题标题】:How to select all non-black pixels in a NumPy array?如何选择 NumPy 数组中的所有非黑色像素?
【发布时间】:2019-03-15 01:41:26
【问题描述】:

我正在尝试使用 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)

【问题讨论】:

    标签: python image numpy image-processing


    【解决方案1】:

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

    non_black_indices = np.nonzero(cv2.cvtColor(img,cv2.COLOR_BGR2GRAY))
    

    然后把所有的黑色像素都改成白色,例如:

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

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

    【讨论】:

      【解决方案2】:

      您应该使用np.any 而不是np.all 来选择除黑色以外的所有像素的第二种情况:

      np.any(image != [0, 0, 0], axis=-1)
      

      或者简单地通过~反转布尔数组来获得黑色像素的补码:

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

      工作示例:

      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()
      


      如果有人使用 matplotlib 绘制结果并得到完全黑色的图像或警告,请参阅此帖子:Converting all non-black pixels into one colour doesn't produce expected output

      【讨论】:

      • 我仍然不清楚为什么它应该是np.any 而不是np.all。我会更多地考虑它并尝试提供解释。但无论如何,我更喜欢使用~
      • 感谢您的回答,我想我现在明白为什么需要 np.any 了。当我使用 np.all 时发生的事情是该数组只包含 R!=0 AND B!=0 AND G!=0 的颜色。这意味着颜色 [255,0,0] 导致 False。通过使用 np.any 条件变为 R!=0 OR B!=0 OR G!=0
      【解决方案3】:

      必要性:需要这种形状的矩阵 = (any,any,3)

      解决方案:

      COLOR = (255,0,0)
      indices = np.where(np.all(mask == COLOR, axis=-1))
      indexes = zip(indices[0], indices[1])
      for i in indexes:
          print(i)
      

      解决方案 2:

      获取特定颜色的区间,例如RED:

      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 个值的矢量。在您拥有带有 Hue 值的 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])
      

      您可以对饱和度和值执行相同的操作。

      【讨论】:

        猜你喜欢
        • 2019-03-28
        • 2021-07-05
        • 2021-06-27
        • 1970-01-01
        • 1970-01-01
        • 2018-09-28
        • 1970-01-01
        • 2021-01-27
        • 1970-01-01
        相关资源
        最近更新 更多