图像HOG特征的生成

本文主要是根据分析一份matlab代码PHOG特征生成的demo得到的,作为总结便于以后使用。

if sum(sum(G))>100
    E = edge(G,'canny');
    [GradientX,GradientY] = gradient(double(G));
    GradientYY = gradient(GradientY);
    Gr = sqrt((GradientX.*GradientX)+(GradientY.*GradientY));
            
    index = GradientX == 0;
    GradientX(index) = 1e-5;
            
    YX = GradientY./GradientX;
    if angle == 180, A = ((atan(YX)+(pi/2))*180)/pi; end
    if angle == 360, A = ((atan2(GradientY,GradientX)+pi)*180)/pi; end
                                
    [bh bv] = anna_binMatrix(A,E,Gr,angle,bin);
else
    bh = zeros(size(I,1),size(I,2));
    bv = zeros(size(I,1),size(I,2));
end
首先需要说明的是G是一幅灰度图,将灰度图看做矩阵进行统计,看看是否有足够的像素产生梯度信息,如果小于100的话,表明整个图像接近于是一幅完全的黑色图像。经过上面的比较之后,再对图像进行canny轮廓处理,得到的图像为0-1二值图像(至于其用处在后面介绍)。紧跟其后是对整个图像求梯度,由于梯度实际上是一个在X或者Y方向上的方向向量,所以后面的GradientY./GradientX就相当于求得某一个像素点处的方向向量(tan=sin/cos)。不过由于GradientX可能等于0,所以在此之前,需要对GradientX做一个调整,将等于0的调整为一个较小的值。由于atan返回的范围是-pi/2到pi/2,所以需要增加一个pi/2作为调整,然后将弧度转化为角度,而下面的atan2函数则适用于当角度为360的时候,实现功能和上面的atan很相似。
function [bm bv] = anna_BinMatrix(A,E,G,angle,bin)
[contorns,n] = bwlabel(E);  
X = size(E,2);
Y = size(E,1);
bm = zeros(Y,X);
bv = zeros(Y,X);

nAngle = angle/bin;

for i=1:n
    [posY,posX] = find(contorns==i);    
    for j=1:size(posY,1)
        pos_x = posX(j,1);
        pos_y = posY(j,1);
        
        b = ceil(A(pos_y,pos_x)/nAngle);
        if b==0, bin= 1; end
        if G(pos_y,pos_x)>0
            bm(pos_y,pos_x) = b;
            bv(pos_y,pos_x) = G(pos_y,pos_x);                
        end
    end
end
bwlabel函数实现将连通域关联起来,并且将所有的连通域进行计数存放到第二个返回值中,第一个返回值是一个和图像一样大小的矩阵,这个矩阵中的第一个连通域填充1,第二个连通域填充2,以此类推。然后利用角度计算每一个直方图中的bin的跨度。利用之前计算出来的角度,得出相应位置上的角度属于直方图的哪一个bin,并且在相应的位置存放角度值。
bh_roi = bh(roi(1,1):roi(2,1),roi(3,1):roi(4,1));
bv_roi = bv(roi(1,1):roi(2,1),roi(3,1):roi(4,1));
p = anna_phogDescriptor(bh_roi,bv_roi,L,bin);
function p = anna_PhogDescriptor(bh,bv,L,bin)
p = [];
%level 0
for b=1:bin
    ind = bh==b;
    p = [p;sum(bv(ind))];
end     
cella = 1;
for l=1:L
    x = fix(size(bh,2)/(2^l));
    y = fix(size(bh,1)/(2^l));
    xx=0;
    yy=0;
    while xx+x<=size(bh,2)
        while yy +y <=size(bh,1) 
            bh_cella = [];
            bv_cella = [];
            
            bh_cella = bh(yy+1:yy+y,xx+1:xx+x);
            bv_cella = bv(yy+1:yy+y,xx+1:xx+x);
            
            for b=1:bin
                ind = bh_cella==b;
                p = [p;sum(bv_cella(ind))];
            end 
            yy = yy+y;
        end        
        cella = cella+1;
        yy = 0;
        xx = xx+x;
    end
end
if sum(p)~=0
    p = p/sum(p);
end
经过之前的代码已经生成了梯度方向了,只需要将这些梯度方向经过统计之后就可以得到一个HOG了。上面的第一个循环就是根据bin的个数统计第一层的直方图。而第二个循环则是根据图像金字塔得到局部的HOG特征,最后进行归一化。

上面是一个很简单的HOG的实现,当然和DPM中的HOG特征不可同日而语,不过对于理解HOG的计算以及生成还是很有帮助的。完整的代码可以到我的资源也下载

你可能感兴趣的:(matlab,hog)