С помощью решение, предоставленное в этом вопросе о разбиении двумерного массива на более мелкие блоки:
def block_view(A, block):
# Reshape the array into a 2D array of 2D blocks, with the resulting axes in the
# order of:
# block row number, pixel row number, block column number, pixel column number
# And then rearrange the axes so that they are in the order:
# block row number, block column number, pixel row number, pixel column number
return A.reshape(A.shape[0]//block[0], block[0], A.shape[1]//block[1], block[1])\
.transpose(0, 2, 1, 3)
# Initial grayscale image
image = np.random.rand(16, 16)
# Boolean array where value is True if corresponding pixel in `image` is
# "black" (intensity less than 0.5)
image_bin = image < 0.5
# Create a 2D array view of 4x4 blocks
a = block_view(image_bin, (4, 4))
# XOR reduce each 4x4 block (i.e. reduce over last two axis), so even number
# of blacks is 0, else 1
a = np.bitwise_xor.reduce(a, axis=(-2, -1))
print(a.astype(np.uint8))
Пример вывода изображения 16x16:
[[0 1 1 0]
[0 0 1 0]
[1 1 1 1]
[0 0 0 1]]
Редактировать:
Функция block_view()
была первоначально реализована после этого ответа (в котором используется as_strided()
), однако после дополнительных поисков вокругЯ решил вместо этого использовать вариант этого ответа (который использует изменение формы).Сроки обоих методов, последний был примерно в 8 раз быстрее (по крайней мере, в результате моего тестирования).