【问题标题】:How to count pixel values satisfying a predicate?如何计算满足谓词的像素值?
【发布时间】:2020-06-18 00:15:43
【问题描述】:

给定一个形状为 (8, 24, 3) 的 NumPy 数组,对应于高度为 8 和宽度为 24 的 HSV 图像,我想计算满足某个函数定义的某个谓词的像素数。

通常使用 NumPy 数组,我们可以这样做:

def isSmall(x):
  return x < 3

a = np.array([1,2,3,4,5])

isSmall(a)
output: array([ True,  True, False, False, False])

什么时候我们可以计算输出中True 值的数量? 我可以对需要三个值的谓词做类似的事情吗? 对应于形状(8, 24, 3)?的数组中的HSV值?

类似这样的:

def isRed(x):
    h, s, v = (x[0], x[1], x[2])
    return ((170 <= h <= 180 or 0 <= h <= 10) and 100 <= s <= 255)

a = image of shape (8,24,3)

isRed(a)
Desired output: array([[ True,  True, ..., False, False],
                      ... , ...
                      [False, True, ..., False, False]])

然而,这会引发形状错误,因为似乎整个数组都被传递给函数,而不是 NumPy 执行其过滤魔法。

【问题讨论】:

    标签: python image numpy filtering vectorization


    【解决方案1】:

    使用 NumPy 的 boolean array indexingbitwise_andbitwise_or 函数(用作 &amp;|)组合这些布尔数组。最后,使用count_nonzero计算结果数组中的True值:

    import cv2
    import numpy as np
    
    
    def is_red(img):
        h, s = cv2.split(cv2.cvtColor(img, cv2.COLOR_BGR2HSV))[:2]
        idx = (((h >= 170) & (h <= 180)) | ((h >= 0) & (h <= 10))) & ((s >= 100) & (s <= 255))
    
        # Just for visual debugging
        cv2.imshow('image', image)
        cv2.imshow('red_mask', idx.astype(np.uint8) * 255)
    
        return idx, np.count_nonzero(idx)
    
    
    image = cv2.imread('images/paddington.png')
    mask, n_pixels = is_red(image)
    print('Red mask:\n', mask, '\n')
    print('Number of red pixels: ', n_pixels)
    
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    这是我的标准测试图片(虽然不符合Setchell's law):

    根据您的截止日期,那将是“红色面具”:

    这就是输出:

    Red mask:
     [[False False False ... False False False]
     [False False False ... False False False]
     [False False False ... False False False]
     ...
     [False False False ... False False False]
     [False False False ... False False False]
     [False False False ... False False False]] 
    
    Number of red pixels:  31938
    

    希望有帮助!

    ----------------------------------------
    System information
    ----------------------------------------
    Platform:    Windows-10-10.0.16299-SP0
    Python:      3.8.1
    NumPy:       1.18.1
    OpenCV:      4.2.0
    

    【讨论】:

    • 正是我想要的,非常感谢!
    【解决方案2】:

    这是使用boolean array indexingbinary bitwise operators 的一种方法:

    a = np.random.randint(0,255,(8,24,3))
    
    h = a[...,0]
    s = a[...,1]
    
    m = (((170 <= h) & (180 >= h)) | ((0 <= h) & (10 >= h))) & ((100 <= s) & (255 >= s))
    
    a[m]
    
    array([[  0, 154,  31],
           [  1, 101,  63],
           [  7, 118, 112],
           [179, 154,  13],
           [170, 163,  58],
           [176, 105, 143],
           [  2, 237, 161],
           [  1, 107,  33],
           [  3, 152, 235],
           [  8, 233, 231],
           [  4, 128,  47],
           [174, 165,  75]])
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-07-21
      • 2019-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多