HOG特征原理梳理与实验分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WL2002200/article/details/51138768

重读了HOG特征的论文,比起SIFT特征这种磨人小妖级别的特征,HOG还是naive. 但HOG特征的使用效果使得其在目前的应用中热度不减。讨论其设计思路是有意思的事情。本文试图从算法的步骤上分析算法设计的意义。但这毕竟是个人观点,各位自己也要判断,要是各位看官阅后理解出现了偏差,乃们自己也有责任。

几个问题

HOG特征也是人工设计的特征,既然是人工设计,那就一定包含了作者的深厚内力在里面,也是充满了经验主义,更多的是实验论证,疗效是关键,而不是理论上的优雅。关于它为什么就这么好,原作者本人也是做了经验上和工程上的分析。
本文主要探讨四个问题,为什么使用局部方向直方图,和作者强调的三个优点:良好的梯度尺度良好的方向和粗糙的空间划分高质量的有交叠的块描述子的局部对比度归一化在HOG特征的设计上是如何体现的。

原理框架

这里写图片描述

输入图像

HOG特征与SIFT特征不同的是它检测窗口尺度固定,通过降采样原始图片来获得与窗口尺寸匹配的输入图像,而SIFT把这部分直接做到了检测算子的构造流程中去。论文中选择64*128的窗口也是根据数据集的特点和待检测目标的性质决定的。

归一化伽马校正与彩色空间

和硕士论文一样,做图像的总喜欢加一个图像的预处理,一来为了凑字数,二来为了保证系统的完整性。在这里作者也试图通过伽马校正来抑制光照的影响,并试图改变色彩空间来提高性能。但针对行人检测,也或许是因为后续步骤对光照已经有较好的抑制,此步骤的引入会降低实验效果。

彩色空间(基准:RGB) 校正方法(基准:无校正) 效果
LAB 近似无区别
灰度 ↓1.5%
平方根 ↓1%
对数压缩 ↓2%

计算梯度(良好的梯度尺度)

作者对图像在x和y方向各做了一个[1 0 -1]的差分,得到了x和y方向的梯度图。但何为良好的梯度尺度呢?好不好都是对比出来的。在做完差分后,一般加一个高斯平滑。但在这里,作者选择了最简单的操作,因为在这个任务中任何使用复杂操作的企图都会导致性能下降。

梯度算子 高斯平滑 效果
1-D point derivatives [1, 0, -1] σ=0 baseline
Cubic corrected 1-D [1, -8, 0, 8, -1] σ=0 ↓1%
1-D point derivatives [-1,1] σ=0 ↓1.5%
2×2 diagonal ones σ=0 ↓1.5%
σ=2 ↓9%

构造cell,bins权重投票(良好的方向和粗糙的空间划分)

与上一节一样,之所以称为良好,是因为比对比试验的结果都好。
作者试验了选取360度方向的情况,效果比180度差。作者最终选择了9个bin,因为试验的其他bin数效果都不如9,18的效果和9差不多,但在作者的评价点上略差。
划分的具体原理是,将方向按照距离相邻两个bin的距离按照幅值按比例划分。

Block的构造(高质量的有交叠的块描述子的局部对比度归一化)

作者将4个cell作为一个block,把每个cell中的9维向量连起来,得到一个block的36维特征,为什么是2×2的4个cell组成一个block,因为作者使用2×1的和1×2的各种试都不如2*2的效果好。
作者滑动block,每个block之间是有重叠的,因为不重叠性能会大幅下降,同时,有重叠也是类似工程问题的通用解决方法。这个过程类似卷积操作的滑动,不做赘述。

归一化

对得到的36维特征做归一化,增强特征间的对比度。作者选择了l2-hys, 即,先做l2-norm,结果中如果有值大于0.2,则截断设置为0.2,再重新做l2-norm.着也是大量实验对比得到的结果。

为什么用局部方向直方图

方向梯度直方图的使用,也是相关工程的通用手法。在形状上下文,SIFT,边缘向直方图等算法中都用到了这种操作。
这里写图片描述
可以看到,梯度的设定能够有效抑制光照导致的像素点绝对值的变化。局部的统计信息能够有效地提高算法的鲁棒性,抑制单一像素点的个体干扰。

论文对应代码实现

一篇简洁易懂的Matlab代码实现,取自网络,版权归原作者所有,侵删。

function [feature] = hog_feature_vector(im)

% The given code finds the HOG feature vector for any given image. HOG
% feature vector/descriptor can then be used for detection of any
% particular object. The Matlab code provides the exact implementation of
% the formation of HOG feature vector as detailed in the paper "Pedestrian
% detection using HOG" by Dalal and Triggs

% INPUT => im (input image)
% OUTPUT => HOG feature vector for that particular image

% Example: Running the code
% >>> im = imread('cameraman.tif');
% >>> hog = hog_feature_vector (im);



% Convert RGB iamge to grayscale
if size(im,3)==3
    im=rgb2gray(im);
end
im=double(im);

rows=size(im,1);
cols=size(im,2);
Ix=im; %Basic Matrix assignment
Iy=im; %Basic Matrix assignment

% Gradients in X and Y direction. Iy is the gradient in X direction and Iy
% is the gradient in Y direction
for i=1:rows-2
    Iy(i,:)=(im(i,:)-im(i+2,:));
end
for i=1:cols-2
    Ix(:,i)=(im(:,i)-im(:,i+2));
end

gauss=fspecial('gaussian',8); %% Initialized a gaussian filter with sigma=0.5 * block width.    

angle=atand(Ix./Iy); % Matrix containing the angles of each edge gradient
angle=imadd(angle,90); %Angles in range (0,180)
magnitude=sqrt(Ix.^2 + Iy.^2);

% figure,imshow(uint8(angle));
% figure,imshow(uint8(magnitude));

% Remove redundant pixels in an image. 
angle(isnan(angle))=0;
magnitude(isnan(magnitude))=0;

feature=[]; %initialized the feature vector

% Iterations for Blocks
for i = 0: rows/8 - 2
    for j= 0: cols/8 -2
        %disp([i,j])

        mag_patch = magnitude(8*i+1 : 8*i+16 , 8*j+1 : 8*j+16);
        %mag_patch = imfilter(mag_patch,gauss);
        ang_patch = angle(8*i+1 : 8*i+16 , 8*j+1 : 8*j+16);

        block_feature=[];

        %Iterations for cells in a block
        for x= 0:1
            for y= 0:1
                angleA =ang_patch(8*x+1:8*x+8, 8*y+1:8*y+8);
                magA   =mag_patch(8*x+1:8*x+8, 8*y+1:8*y+8); 
                histr  =zeros(1,9);

                %Iterations for pixels in one cell
                for p=1:8
                    for q=1:8
%                       
                        alpha= angleA(p,q);

                        % Binning Process (Bi-Linear Interpolation)
                        if alpha>10 && alpha<=30
                            histr(1)=histr(1)+ magA(p,q)*(30-alpha)/20;
                            histr(2)=histr(2)+ magA(p,q)*(alpha-10)/20;
                        elseif alpha>30 && alpha<=50
                            histr(2)=histr(2)+ magA(p,q)*(50-alpha)/20;                 
                            histr(3)=histr(3)+ magA(p,q)*(alpha-30)/20;
                        elseif alpha>50 && alpha<=70
                            histr(3)=histr(3)+ magA(p,q)*(70-alpha)/20;
                            histr(4)=histr(4)+ magA(p,q)*(alpha-50)/20;
                        elseif alpha>70 && alpha<=90
                            histr(4)=histr(4)+ magA(p,q)*(90-alpha)/20;
                            histr(5)=histr(5)+ magA(p,q)*(alpha-70)/20;
                        elseif alpha>90 && alpha<=110
                            histr(5)=histr(5)+ magA(p,q)*(110-alpha)/20;
                            histr(6)=histr(6)+ magA(p,q)*(alpha-90)/20;
                        elseif alpha>110 && alpha<=130
                            histr(6)=histr(6)+ magA(p,q)*(130-alpha)/20;
                            histr(7)=histr(7)+ magA(p,q)*(alpha-110)/20;
                        elseif alpha>130 && alpha<=150
                            histr(7)=histr(7)+ magA(p,q)*(150-alpha)/20;
                            histr(8)=histr(8)+ magA(p,q)*(alpha-130)/20;
                        elseif alpha>150 && alpha<=170
                            histr(8)=histr(8)+ magA(p,q)*(170-alpha)/20;
                            histr(9)=histr(9)+ magA(p,q)*(alpha-150)/20;
                        elseif alpha>=0 && alpha<=10
                            histr(1)=histr(1)+ magA(p,q)*(alpha+10)/20;
                            histr(9)=histr(9)+ magA(p,q)*(10-alpha)/20;
                        elseif alpha>170 && alpha<=180
                            histr(9)=histr(9)+ magA(p,q)*(190-alpha)/20;
                            histr(1)=histr(1)+ magA(p,q)*(alpha-170)/20;
                        end


                    end
                end
                block_feature=[block_feature histr]; % Concatenation of Four histograms to form one block feature

            end
        end
        % Normalize the values in the block using L2-Norm
        block_feature=block_feature/sqrt(norm(block_feature)^2+.01);

        feature=[feature block_feature]; %Features concatenation
    end
end

feature(isnan(feature))=0; %Removing Infinitiy values

% Normalization of the feature vector using L2-Norm
feature=feature/sqrt(norm(feature)^2+.001);
for z=1:length(feature)
    if feature(z)>0.2
         feature(z)=0.2;
    end
end

%renormalization
feature=feature/sqrt(norm(feature)^2+.001);        

% toc;       

延伸

DPM算法
OpenCV人脸识别中HOG特征的实现

阅读更多
换一批

没有更多推荐了,返回首页