如何计算满足谓词的像素值?

How to count pixel values satisfying a predicate?

给定一个形状为 (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 个值的数量? 我可以对需要三个值的谓词做类似的事情吗? 对应于形状数组中的 HSV 值 (8, 24, 3)?

像这样:

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 执行其过滤魔法。

使用 NumPy 的 boolean array indexing, and the bitwise_and and bitwise_or functions (used as & and |) to combine these boolean arrays. At last, count True values in the resulting array using count_nonzero:

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

这是我的标准测试图像(虽然不符合):

根据您的要求,这就是“红色面具”:

这就是输出:

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

这是使用 boolean array indexing and binary 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]])