我有一段MATLAB代码,它从图像中提取91x91像素块,并使用HOG提取其特征向量。我想用Python重写这个函数。我一直在努力寻找如何在Python中获得与在MATLAB中相同的HOG返回值,但未能做到。如果您能提供任何帮助,我将不胜感激。
VLFeat库(http://www.vlfeat.org/overview/hog.html)在MATLAB代码中使用,我在Python中使用scikit图像(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单个。使用23的单元大小和4的取向数目来应用HoG。
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_blockssy的计算公式为:
n_blocksx = (n_cellsx - bx) + 1
n_blocksy = (n_cellsy - by) + 1
n_cellsx是:x中的单元格数,此处的值为4,n_cellsy也是;bx,by是cells_per_block,它是(1,1);在这种情况下,方位是4。
返回值的大小(normalised_blocks)似乎是通过4*4*1*1*4(n_blocksy*n_blocksx*by*bx*orientations)计算的
我试着改变区块大小,但仍然无法达到预期。。。(当块大小为(2,2)时,返回值为144*1数组)
有人能帮忙吗。。。如何获得与Matlab中相同的Hog输出?非常感谢。
VLFeat库与scikit镜像相比做了一些不同的事情。VLFeat库返回9个(方向数)对比度不敏感、18个对比度敏感和4个维度,这些维度以正方形块(包含四个单元)捕获整体梯度能量。因此,它每个单元输出31个维度。然而,scikit图像程序是不同的,我认为你已经很好地理解它。
根据我的经验,如果你想使用scikit图像和MATLAB找到相同的HoG向量,你肯定至少应该为scikit图像设置cells_per_block= (2,2)
。