Python 使用 cv2 将像素值映射到它的直方图 bin

Python map pixel value to it's histogram bin with cv2

给定一张图像,有没有一种快速的方法可以将像素值映射到它的 bin 中?

img = cv2.imread('test_image.jpg')
hist_g = cv2.calcHist([img[x:x+w,y:y+h,:]], [1], None, [9], [0, 256])

这个 return 是一个 9x1 数组,其中的像素数落入 0 - 256 范围内的 9 个区间。我认为。

我想要的是 [x:x+w,y:y+h] 矩阵,每个条目都有像素映射到的 bin 编号。我该怎么做?

例如,假设我有矩阵

x = np.array([[154, 192],[67,115]])

我要return矩阵

x_histcounts = np.array([[5, 7],[3,4]])

基于cv2.calcHist([img[x:x+w,y:y+h,:]], [1], None, [9], [0, 256])

因为 154 在第 5 个 bin 中,192 在第 7 个 bin 中,依此类推

如果你想将像素映射到 9 分箱,那么你可以转换为灰度,然后使用 // 除以 (256/9) 得到整数

img_gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

result = img_gray[x:x+w,y:y+h] // (256/9)

calcHist 中,您使用通道列表 [1],因此您只需要一个通道的直方图,这意味着您不必转换为灰度,而是使用 [..., ..., 1]

result = img[x:x+w, y:y+h, 1] // (256/9)

编辑: 我测试了你的示例数据 [[154, 192], [67, 115]] 它给了我 [[5, 6], [2, 4]] 而不是 [[5, 7], [3, 4]]

import numpy as np

bins_number = 9

x = np.array([[154, 192], [67, 115]])
result = (x // (256/bins_number)).astype(int)

print('result:', result.tolist())

使用 Google "numpy histcounts matlab" 我还发现 使用 np.digitize() 来复制 histcounts 并且它也给了我 [[5, 6], [2, 4]] 而不是[[5, 7], [3, 4]] 但我不知道我是否正确创建了 bin 范围。

import numpy as np

bins_number = 9

x = np.array([[154, 192], [67, 115]])

bins = [(256/bins_number)*x for x in range(1, bins_number+1)]
result = np.digitize(x, bins)

print('result:', result.tolist())
print('bins:', bins)

我没有 Matlab 所以我尝试在 Octave

中使用 histc()
>> [a, b] = histc([154, 192, 67, 115], [ 28.44444444,  56.88888889,  
85.33333333, 113.77777778, 142.22222222, 170.66666667, 199.11111111, 227.55555556, 256. ])

a =

   0   1   0   1   1   1   0   0   0

b =

   5   6   2   4

它也给了我 [[5, 6], [2, 4]] 而不是 [[5, 7], [3, 4]]


编辑: 我发现 numpy.histogram_bin_edges 生成 bin 范围

import numpy as np

bins_number = 9

x = np.array([[154, 192], [67, 115], [0,1]])

bins = np.histogram_bin_edges(x, bins=9, range=(0, 256))

print('bins:', bins)

但它添加了 0 作为第一个边缘,所以稍后它使用数字 1-9 而不是 0-8 但是如果你使用 bins[1:] 那么它仍然使用数字 0-8

import numpy as np

bins_number = 9

x = np.array([[154, 192], [67, 115]])

bins = np.histogram_bin_edges(x, bins=9, range=(0, 255))
print('bins:', bins)

print('result:', np.digitize(x, bins[1:]).tolist())