numpy 2d数组(坐标)需要分配到3D数组,到某个特定的bin

时间:2013-07-15 18:17:49

标签: python arrays opencv numpy indexing

我有以下代码用8个箱子计算HOG图像并预先计算Sobel X和Y滤波图像:

for y in xrange(0, 480):
    for x in xrange(0, 640):
        base_angle = np.arctan2(sobel_Y[y,x], sobel_X[y,x]) * 180/np.pi
        if base_angle < 0: base_angle += 360
        angle = int(round(base_angle / 45))
        if angle == 8: angle = 0
        hog[y,x,angle] += np.sqrt(sobel_X[y,x]**2 + sobel_Y[y,x]**2)

我试图修改它以避免循环:

base_angle = np.arctan2(sobel_Y, sobel_X) * 180/np.pi
base_angle[base_angle < 0] += 360
angle =(base_angle / 45).round().astype(np.uint8)
angle[angle == bins] = 0
hog[:,:,angle] += np.sqrt(sobel_X**2 + sobel_Y**2)

但是,最后一个表达式没有正确计算。我基本上需要的是根据来自角度数组的索引,在hog数组的每个(y,x)点处将幅度(np.sqrt ...表达式)添加到hog数组。任何解决方案?

1 个答案:

答案 0 :(得分:2)

使用

magnitude = np.sqrt(sobel_X**2 + sobel_Y**2)
Y, X = np.ogrid[0:angle.shape[0], 0:angle.shape[1]]
hog[Y, X, angle] += magnitude

更新hog


import numpy as np

def using_for_loop(hog, sobel_Y, sobel_X):
    for y in xrange(0, sobel_Y.shape[0]):
        for x in xrange(0, sobel_X.shape[1]):
            base_angle = np.arctan2(sobel_Y[y, x], sobel_X[y, x]) * 180 / np.pi
            if base_angle < 0:
                base_angle += 360
            angle = int(round(base_angle / 45))
            if angle == 8:
                angle = 0
            hog[y, x, angle] += np.sqrt(sobel_X[y, x] ** 2 +
                                        sobel_Y[y, x] ** 2)
    return hog

def using_indexing(hog, sobel_Y, sobel_X):
    base_angle = np.arctan2(sobel_Y, sobel_X) * 180 / np.pi
    base_angle[base_angle < 0] += 360
    angle = (base_angle / 45).round().astype(np.uint8)
    angle[angle == bins] = 0
    magnitude = np.sqrt(sobel_X ** 2 + sobel_Y ** 2)
    Y, X = np.ogrid[0:angle.shape[0], 0:angle.shape[1]]
    hog[Y, X, angle] += magnitude
    return hog

bins = 8
sobel_Y, sobel_X = np.meshgrid([1, 2, 3], [4, 5, 6, 7])
# hog = np.zeros(sobel_X.shape + (bins,))
hog = np.random.random(sobel_X.shape + (bins,))
answer = using_for_loop(hog, sobel_Y, sobel_X)
result = using_indexing(hog, sobel_Y, sobel_X)
assert np.allclose(answer, result)

请注意,如果

In [62]: angle.shape
Out[62]: (4, 3)

然后

In [74]: hog[:,:,angle].shape
Out[74]: (4, 3, 4, 3)

这不是正确的形状。相反,如果你定义

In [75]: Y, X = np.ogrid[0:angle.shape[0], 0:angle.shape[1]]

然后hog[Y, X, angle]具有与magnitude相同的形状:

In [76]: hog[Y, X, angle].shape
Out[76]: (4, 3)

In [77]: magnitude = np.sqrt(sobel_X ** 2 + sobel_Y ** 2)

In [78]: magnitude.shape
Out[78]: (4, 3)

当然,这并不能证明hog[Y, X, angle]是正确的表达方式,但它相当于物理学家的dimensionality check,这表明我们至少可以走上正轨。


使用NumPy fancy indexing,当YXangle具有相同的形状(或广播到相同的形状)时,

hog[Y, X, angle]

也将具有相同的形状。 (i,j)中的hog[Y, X, angle]元素将等于

hog[Y[i,j], X[i,j], angle[i,j]]

这就是hog[Y, X, angle] += magnitude有效的原因。