% Image descriptor based on Histogram of Orientated Gradients (HOG) for
% gray-level images. The original code was developed for the work
% O. Ludwig, D. Delgado, V. Goncalves, and U. Nunes, "Trainable Classifier-Fusion 
% Schemes: An Application To Pedestrian Detection," in 12th Int. IEEE Conf. 
% Intelligent Transportation Systems, 2009, St. Louis, 2009. vol.1, pp. 432-437. 
% This code was an outcome of major revisions by W.-S. Lu at University of Victoria.
% Last updated: July 19, 2021.
% Input:
% Im: input image. 
% d: signifies size of basic image patch to perform HOG.
%    Typically d is between 3 and 7.
% B: number of histogram bins. Typically B is set between 7 and 9. 
% Output:
% h: HOG feature vector of input image.
function h = hog20new(Im,d,B)
t = floor(d/2);
[N,M] = size(Im);
k1 = (M-d)/t;
c1 = ceil(k1);
k2 = (N-d)/t;
c2 = ceil(k2);
if c1 - k1 > 0
   M1 = d + t*c1;
   Im = [Im fliplr(Im(:,(2*M-M1+1):M))];
end
if c2 - k2 > 0
   N1 = d + t*c2;
   Im = [Im; flipud(Im((2*N-N1+1):N,:))];
end
[N,M] = size(Im);
nx1 = 1:t:M-d+1;
nx2 = d:t:M;
ny1 = 1:t:N-d+1;
ny2 = d:t:N;
Lx = length(nx1);
Ly = length(ny1);
h = zeros(Lx*Ly*B,1); 
Im = double(Im);
Gx = [Im(:,2:M) zeros(N,1)] - [zeros(N,1) Im(:,1:M-1)];
Gy = [zeros(1,M); Im(1:N-1,:)] - [Im(2:N,:); zeros(1,M)];
mag = sqrt(((Gx.^2) + (Gy.^2))); 
ang = atan2(Gy,Gx);
c3 = (B-1e-6)/(2*pi);
I = round((ang+pi)*c3 + 0.5); % map ang to B bins.
k = 1;
zb = zeros(B,1);
Lt = d^2;
for m = 1:Lx
    for n = 1:Ly
        ht = zb;
        mag1 = mag(ny1(n):ny2(n),nx1(m):nx2(m));
        ang1 = I(ny1(n):ny2(n),nx1(m):nx2(m));
        mag2 = mag1(:);
        ang2 = ang1(:);
        for i = 1:Lt
            ai = ang2(i);
            ht(ai) = ht(ai) + mag2(i);
        end
        if norm(ht) ~= 0
           ht = ht/(norm(ht)+0.01);
        end
        h((k-1)*B+1:k*B) = ht;
        k = k + 1;
    end
end