代码之家  ›  专栏  ›  技术社区  ›  JS Lavertu

如何确定numpy数组是否包含沿第三维的向量?

  •  0
  • JS Lavertu  · 技术社区  · 5 年前

    我想知道3D numpy数组是否包含沿第三维的特定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值,从而绕过了这个问题。这使得执行速度提高了几个数量级。

    0 回复  |  直到 5 年前
        1
  •  2
  •   Stefan B    5 年前

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

    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
    
        2
  •  1
  •   Jacob Faib    5 年前

    如果你的数组是整数,你可以使用 numpy.array_equal() 检查数组是否匹配(如果使用 float 你看 numpy.allclose() 相反)。假设要匹配的子数组始终位于第三个子行中,您可以执行以下操作:

    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))
    
        3
  •  0
  •   JS Lavertu    5 年前

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

    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)
    

    此外,它的好处是为目标颜色提供了一点灵活性。