|
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 |
|