Я предполагаю, что вы хотите три гистограммы по 8 бинов для каждого патча, по одной для каждого цветового канала.Если данные вашего изображения uint8
, то мы можем получить соответствующий индекс бина для каждого пикселя, сдвинув вправо на пять битов.Фактическое гистограммирование может быть выполнено с использованием np.bincount
+ некоторого небольшого обмана, чтобы обойти его только как 1D.
Это по существу однострочник.Большая часть кода ниже посвящена работе с изображениями, размер которых не кратен 32.
import numpy as np
def histo24(img):
h, w, c = img.shape
assert c == 3
assert img.dtype == np.uint8
# pad
H, W = (h+31)>>5, (w+31)>>5
patches = np.zeros((H, 32, W, 32, 3), np.uint8)
patches.reshape(H<<5, W<<5, 3)[:h, :w] = img>>5
# the next line is the actual histogramming
histo = np.bincount(
(patches + np.arange(0, H*W*24, 8).reshape(H, 1, W, 1, 3)).ravel(),
minlength=H*W*24).reshape(H, W, 24)
# subtract padded zeros from zero bins at the right and bottom edges
if h & 31:
histo[-1, :, ::8] -= (31&-h)<<5
if w & 31:
histo[:, -1, ::8] -= (31&-w)<<5
if h & 31:
histo[-1, -1, ::8] += (31&-h)*(31&-w)
return histo
Пример:
Код например:
def visualize(histo):
h, w, c = histo.shape
assert c == 24
vis = np.zeros((h, 32, w, 32, 3), np.uint8)
idx = np.arange(28)[None, :, None]
for c in range(3):
bnds = (histo[..., c<<3:(c+1)<<3].cumsum(axis=-1)*(28/1024)).astype(np.uint8)[..., ::-1]
for j in range(1, 8):
view = vis[:, 2:-2, :, 7*c+6:7*c+12, c]
view[..., 0][(idx >= bnds[:, None, :, j]) &
(idx < bnds[:, None, :, j - 1])] = (j<<5)|16
view[..., 1:] = view[..., :1]
return vis.reshape(h<<5, w<<5, 3)
from scipy.misc import face
import Image
exmpl = face()
histo = histo24(exmpl)
Image.fromarray(exmpl).show()
#Image.fromarray(exmpl>>5<<5).show()
Image.fromarray(visualize(histo)).show()