a b/functions/functions_FeatExtr/HashingHist.m
1
function [f, BlkIdx] = HashingHist(PCANet, ImgIdx, OutImg)
2
% Output layer of PCANet (Hashing plus local histogram)
3
% ========= INPUT ============
4
% PCANet  PCANet parameters (struct)
5
%       .PCANet.NumStages      
6
%           the number of stages in PCANet; e.g., 2  
7
%       .PatchSize
8
%           the patch size (filter size) for square patches; e.g., [5 3]
9
%           means patch size equalt to 5 and 3 in the first stage and second stage, respectively 
10
%       .NumFilters
11
%           the number of filters in each stage; e.g., [16 8] means 16 and
12
%           8 filters in the first stage and second stage, respectively
13
%       .HistBlockSize 
14
%           the size of each block for local histogram; e.g., [10 10]
15
%       .BlkOverLapRatio 
16
%           overlapped block region ratio; e.g., 0 means no overlapped 
17
%           between blocks, and 0.3 means 30% of blocksize is overlapped 
18
%       .Pyramid
19
%           spatial pyramid matching; e.g., [1 2 4], and [] if no Pyramid
20
%           is applied
21
% ImgIdx  Image index for OutImg (column vector)
22
% OutImg  PCA filter output before the last stage (cell structure)
23
% ========= OUTPUT ===========
24
% f       PCANet features (each column corresponds to feature of each image)
25
% BlkIdx  index of local block from which the histogram is compuated
26
% ============================
27
% addpath('./Utils')
28
29
30
NumImg = max(ImgIdx);
31
f = cell(NumImg,1);
32
map_weights = 2.^((PCANet.NumFilters(end)-1):-1:0); % weights for binary to decimal conversion
33
34
for Idx = 1:NumImg
35
  
36
    Idx_span = find(ImgIdx == Idx);
37
    NumOs = length(Idx_span)/PCANet.NumFilters(end); % the number of "O"s
38
    Bhist = cell(NumOs,1);
39
    
40
    for i = 1:NumOs 
41
        
42
        T = 0;
43
        ImgSize = size(OutImg{Idx_span(PCANet.NumFilters(end)*(i-1) + 1)});
44
        for j = 1:PCANet.NumFilters(end)
45
            T = T + map_weights(j)*Heaviside(OutImg{Idx_span(PCANet.NumFilters(end)*(i-1)+j)}); 
46
            % weighted combination; hashing codes to decimal number conversion
47
            
48
            OutImg{Idx_span(PCANet.NumFilters(end)*(i-1)+j)} = [];
49
        end
50
        
51
        
52
        if isempty(PCANet.HistBlockSize)
53
            NumBlk = ceil((PCANet.ImgBlkRatio - 1)./PCANet.BlkOverLapRatio) + 1;
54
            HistBlockSize = ceil(size(T)./PCANet.ImgBlkRatio);
55
            OverLapinPixel = ceil((size(T) - HistBlockSize)./(NumBlk - 1));
56
            NImgSize = (NumBlk-1).*OverLapinPixel + HistBlockSize;
57
            Tmp = zeros(NImgSize);
58
            Tmp(1:size(T,1), 1:size(T,2)) = T;
59
            Bhist{i} = sparse(histc(im2col_general(Tmp,HistBlockSize,...
60
            OverLapinPixel),(0:2^PCANet.NumFilters(end)-1)')); 
61
        else 
62
            
63
            stride = round((1-PCANet.BlkOverLapRatio)*PCANet.HistBlockSize); 
64
            blkwise_fea = sparse(histc(im2col_general(T,PCANet.HistBlockSize,...
65
              stride),(0:2^PCANet.NumFilters(end)-1)')); 
66
            % calculate histogram for each local block in "T"
67
            
68
           if ~isempty(PCANet.Pyramid)
69
                x_start = ceil(PCANet.HistBlockSize(2)/2);
70
                y_start = ceil(PCANet.HistBlockSize(1)/2);
71
                x_end = floor(ImgSize(2) - PCANet.HistBlockSize(2)/2);
72
                y_end = floor(ImgSize(1) - PCANet.HistBlockSize(1)/2);
73
                
74
                sam_coordinate = [...
75
                    kron(x_start:stride:x_end,ones(1,length(y_start:stride: y_end))); 
76
                    kron(ones(1,length(x_start:stride:x_end)),y_start:stride: y_end)];               
77
                
78
                blkwise_fea = spp(blkwise_fea, sam_coordinate, ImgSize, PCANet.Pyramid)';
79
                
80
           else
81
                blkwise_fea = bsxfun(@times, blkwise_fea, ...
82
                    2^PCANet.NumFilters(end)./sum(blkwise_fea)); 
83
           end
84
           
85
           Bhist{i} = blkwise_fea;
86
        end
87
        
88
    end           
89
    f{Idx} = vec([Bhist{:}]');
90
    
91
    if ~isempty(PCANet.Pyramid)
92
        f{Idx} = sparse(f{Idx}/norm(f{Idx}));
93
    end
94
end
95
f = [f{:}];
96
97
if ~isempty(PCANet.Pyramid)
98
    BlkIdx = kron((1:size(Bhist{1},1))',ones(length(Bhist)*size(Bhist{1},2),1));
99
else
100
    BlkIdx = kron(ones(NumOs,1),kron((1:size(Bhist{1},2))',ones(size(Bhist{1},1),1)));
101
end
102
103
%-------------------------------
104
function X = Heaviside(X) % binary quantization
105
X = sign(X);
106
X(X<=0) = 0;
107
108
function x = vec(X) % vectorization
109
x = X(:);
110
111
112
function beta = spp(blkwise_fea, sam_coordinate, ImgSize, pyramid)
113
114
[dSize, ~] = size(blkwise_fea);
115
116
img_width = ImgSize(2);
117
img_height = ImgSize(1);
118
119
% spatial levels
120
pyramid_Levels = length(pyramid);
121
pyramid_Bins = pyramid.^2;
122
tBins = sum(pyramid_Bins);
123
124
beta = zeros(dSize, tBins);
125
cnt = 0;
126
127
for i1 = 1:pyramid_Levels,
128
    
129
    Num_Bins = pyramid_Bins(i1);
130
    
131
    wUnit = img_width / pyramid(i1);
132
    hUnit = img_height / pyramid(i1);
133
    
134
    % find to which spatial bin each local descriptor belongs
135
    xBin = ceil(sam_coordinate(1,:) / wUnit);
136
    yBin = ceil(sam_coordinate(2,:) / hUnit);
137
    idxBin = (yBin - 1)*pyramid(i1) + xBin;
138
    
139
    for i2 = 1:Num_Bins,     
140
        cnt = cnt + 1;
141
        sidxBin = find(idxBin == i2);
142
        if isempty(sidxBin),
143
            continue;
144
        end      
145
        beta(:, cnt) = max(blkwise_fea(:, sidxBin), [], 2);
146
    end
147
end
148
149