【问题标题】:How to find if numpy array contains vector along 3rd dimension?如何查找numpy数组是否包含沿第三维的向量?
【发布时间】:2021-05-16 14:32:33
【问题描述】:

我想查找 3D numpy 数组是否包含沿第 3 维的特定 1D 向量。 (我需要检查图像是否包含特定颜色的像素。)

当且仅当任何像素与目标完全匹配时,我才需要返回 true。

我尝试了以下方法:

import numpy as np
target = np.array([255, 0, 0])
search_area = np.array([[[0,0,0],[1,1,1],[2,2,2]],
                        [[3,3,3],[4,4,4],[5,5,5]],
                        [[6,6,6],[7,7,7],[8,8,255]]])
contains_target = np.isin(target, search_area).all():  # Returns True

返回 True,因为每个元素都可以在整个数组中的某个位置单独找到。

接下来我尝试了:

target = np.array([255, 0, 0])
search_area = np.array([[[0,0,0],[1,1,1],[2,2,2]],
                        [[3,3,3],[4,4,4],[5,5,5]],
                        [[6,6,6],[7,7,7],[8,0,255]]])
contains_target = (target == search.all(2)).any()  # Returns True

这效果更好,因为它单独匹配每个像素的目标元素,但当它们没有按顺序或数字不正确时,它仍然返回 True。

最后,我试过了:

def pixel_matches_target(self, pixel_to_match):
        return (target == pixel_to_match).all()

contains_target = np.apply_along_axis(self.pixel_matches_target, 2, search_area).any()

但是使用起来太慢了(每次大约需要 1 秒)。

如何查找 numpy 数组是否包含沿特定轴的向量?


编辑:

我最终通过使用 cv2.inRange() 将 RGB 图像转换为二进制掩码并检查生成的 2D 数组是否包含 True 值来规避该问题。这导致执行速度提高了几个数量级。

【问题讨论】:

    标签: python arrays python-3.x numpy multidimensional-array


    【解决方案1】:

    注意:这不能回答一般问题,但对于查找图像是否包含特定颜色的像素的特定问题来说,速度要快几个数量级。

    import cv2
    import numpy
    
    target_lower = np.array([250, 0, 0])
    target_upper = np.array([255, 5, 5])
    search_area = np.array([[[0,0,0],[1,1,1],[2,2,2]],
                            [[3,3,3],[4,4,4],[5,5,5]],
                            [[6,6,6],[7,7,7],[8,0,255]]])
    
    mask = cv2.inRange(search_area, target_lower, target_upper)
    mask = mask.astype(bool)
    
    contains_target = (True in mask)
    

    此外,它还有一个好处是可以为目标颜色提供一些灵活性。

    【讨论】:

      【解决方案2】:

      如果您的数组是整数,您可以使用numpy.array_equal() 来检查数组是否匹配(如果使用floats,请参阅numpy.allclose())。假设要匹配的子数组总是在第 3 个子行中,您可以执行以下操作:

      if sum(np.array_equal(target,a) for a in arr[:,2]):
          # Contains the target!
      

      如果子数组出现在任何你可以使用的地方:

      sum(np.array_equal(target,item) for sublist in arr for item in sublist))
      

      【讨论】:

      • 子数组可以在数组中的任何位置。有什么方法可以调整您的解决方案吗?
      • @JSLavertu 我编辑了帖子以说明在任何地方发生的元素
      【解决方案3】:

      解决您的问题的一个不错的可能性是(如果您能负担得起额外的临时内存):

      import numpy as np
      
      target = np.array([255, 0, 0])
      search_area = np.array([[[0,0,0],[1,1,1],[2,2,2]],
                              [[3,3,3],[4,4,4],[5,5,5]],
                              [[6,6,6],[7,7,7],[8,0,255]]])
      
      # works for general N-D sub-arrays
      adjusted_shape = search_area.reshape((-1, *target.shape))
      
      contains_target = target.tolist() in adjusted_shape.tolist() # False
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-01-22
        相关资源
        最近更新 更多