为什么Python的Hog输出(scikit-image)与MATLAB的Hog(vlfeat)不同?

2 投票
1 回答
1779 浏览
提问于 2025-04-19 04:26

我有一段MATLAB代码,它从一张图片中提取了一个91x91的像素块,并使用HOG(方向梯度直方图)来提取特征向量。我想把这个功能用Python重写。可是我一直在努力寻找如何在Python中得到和MATLAB一样的HOG返回值,但一直没有成功。如果你能提供一些帮助,我将非常感激。

在MATLAB代码中使用了VLFeat库(http://www.vlfeat.org/overview/hog.html),而我在Python中使用的是scikit-image库(http://scikit-image.org/docs/dev/api/skimage.feature.html?highlight=peak_local_max#skimage.feature.hog)。

在MATLAB中,输入的'im2single(patch)'是一个91*91的数组,而HOG返回的数据类型是4*4*16的单精度浮点数。HOG的单元格大小设置为23,方向数为4。

     hog = vl_hog(im2single(patch),23, 'variant', 'dalaltriggs', 'numOrientations',4) ;

返回的数据是4*4*16的单精度浮点数,可以以以下形式显示:

     val(:,:,1) =

     0         0         0         0
     0         0         0         0
     0    0.2000    0.2000    0.0083
     0    0.2000    0.2000    0.0317

     ....

     val(:,:,16) =

     0         0         0         0
     0         0         0         0
     0         0    0.0526    0.0142
     0         0    0.2000    0.2000

然后结果被手动展平为一个256*1的特征向量。总的来说,在一个91*91的像素块中,提取出了一个256*1的特征向量。现在我想在Python中得到相同的结果。

在我的Python代码中,我尝试用相同的单元格大小和方向数来应用HOG。块大小设置为(1,1)。

    tc = hog(repatch, orientations=4, pixels_per_cell=(23,23), cells_per_block= (1,1), visualise=False, normalise=False)

我把像素块的大小增加到92*92,这样块的大小就是单元格大小的整数倍。现在输入数组叫做'repatch'。但是,输出'tc'是一个64*1的数组(梯度直方图被展平为特征向量)。

   tc.shape 

   (64,)

然后我查看了Skimage的源代码,

    orientation_histogram = np.zeros((n_cellsy, n_cellsx, orientations))
    orientation_histogram.shape 
    (4, 4, 4)

这里的n_cellsx是x方向上的单元格数量,n_cellsy是y方向上的单元格数量。看起来HOG的输出与方向直方图的维度关系很大。

实际返回的HOG值的维度由以下公式决定:

    normalised_blocks = np.zeros((n_blocksy, n_blocksx,by, bx, orientations))

其中n_blocksy和n_blocksx是通过以下公式计算的:

    n_blocksx = (n_cellsx - bx) + 1
    n_blocksy = (n_cellsy - by) + 1

n_cellsx是x方向上的单元格数量,这里是4,n_cellsy也是如此;bx和by是每个块的单元格数量,这里是(1,1);方向数在这个例子中是4。

看起来返回值的大小(normalised_blocks)是通过4*4*1*1*4计算得出的(n_blocksy * n_blocksx * by * bx * orientations)。

我尝试改变块大小,但仍然无法得到我期望的结果……(当块大小为(2,2)时,返回值是一个144*1的数组)。

有没有人能帮帮我……我该如何在Python中得到和MATLAB一样的HOG输出呢?非常感谢。

1 个回答

1

VLFeat库和scikit-image库的工作方式不太一样。VLFeat库会返回9个与方向无关的特征、18个与对比度有关的特征,以及4个维度,这些特征可以捕捉到方块中的整体梯度能量(每个方块包含四个小单元)。所以它每个小单元会输出31个特征。不过,scikit-image的处理方式就不同了,我想你对它应该有一定的了解。

根据我的经验,如果你想用scikit-image和MATLAB找到相同的HoG向量,你至少需要在scikit-image中设置cells_per_block= (2,2)

撰写回答