1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 package org.openimaj.image.feature.dense.gradient.binning;
31
32 import org.openimaj.citation.annotation.Reference;
33 import org.openimaj.citation.annotation.ReferenceType;
34 import org.openimaj.image.analysis.algorithm.histogram.WindowedHistogramExtractor;
35 import org.openimaj.image.analysis.algorithm.histogram.binning.SpatialBinningStrategy;
36 import org.openimaj.math.geometry.shape.Rectangle;
37 import org.openimaj.math.statistics.distribution.Histogram;
38 import org.openimaj.util.array.ArrayUtils;
39
40
41
42
43
44
45
46
47
48
49
50 @Reference(
51 type = ReferenceType.Inproceedings,
52 author = { "Dalal, Navneet", "Triggs, Bill" },
53 title = "Histograms of Oriented Gradients for Human Detection",
54 year = "2005",
55 booktitle = "Proceedings of the 2005 IEEE Computer Society Conference on Computer Vision and Pattern Recognition (CVPR'05) - Volume 1 - Volume 01",
56 pages = { "886", "", "893" },
57 url = "http://dx.doi.org/10.1109/CVPR.2005.177",
58 publisher = "IEEE Computer Society",
59 series = "CVPR '05",
60 customData = {
61 "isbn", "0-7695-2372-2",
62 "numpages", "8",
63 "doi", "10.1109/CVPR.2005.177",
64 "acmid", "1069007",
65 "address", "Washington, DC, USA"
66 })
67 public class FixedHOGStrategy implements SpatialBinningStrategy {
68
69
70
71
72
73
74 public enum BlockNormalisation {
75
76
77
78 L1 {
79 @Override
80 final void normalise(Histogram h, int blockArea) {
81 h.normaliseL1();
82 }
83 },
84
85
86
87 L2 {
88 @Override
89 final void normalise(Histogram h, int blockArea) {
90
91
92 ArrayUtils.divide(h.values, blockArea);
93 }
94 },
95
96
97
98 L1sqrt {
99 @Override
100 final void normalise(Histogram h, int blockArea) {
101 h.normaliseL1();
102
103 for (int x = 0; x < h.values.length; x++)
104 h.values[x] = Math.sqrt(h.values[x]);
105 }
106 },
107
108
109
110 L2clip {
111 @Override
112 final void normalise(Histogram h, int blockArea) {
113
114
115 double sumsq = 0;
116 for (int x = 0; x < h.values.length; x++) {
117 h.values[x] = h.values[x] / blockArea;
118 if (h.values[x] > 0.2)
119 h.values[x] = 0.2;
120 sumsq += h.values[x] * h.values[x];
121 }
122
123 final double invNorm = 1.0 / Math.sqrt(sumsq);
124 for (int x = 0; x < h.values.length; x++) {
125 h.values[x] *= invNorm;
126 }
127 }
128 };
129
130 abstract void normalise(Histogram h, int blockArea);
131 }
132
133 int cellWidth = 6;
134 int cellHeight = 6;
135 int cellsPerBlockX = 3;
136 int cellsPerBlockY = 3;
137 int blockStepX = 1;
138 int blockStepY = 1;
139 BlockNormalisation norm = BlockNormalisation.L2;
140
141
142
143
144
145
146
147
148
149
150
151
152
153 public FixedHOGStrategy(int cellSize, int cellsPerBlock, BlockNormalisation norm) {
154 this(cellSize, cellsPerBlock, 1, norm);
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170 public FixedHOGStrategy(int cellSize, int cellsPerBlock, int blockStep, BlockNormalisation norm) {
171 this(cellSize, cellSize, cellsPerBlock, cellsPerBlock, blockStep, blockStep, norm);
172 }
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195 public FixedHOGStrategy(int cellWidth, int cellHeight, int cellsPerBlockX, int cellsPerBlockY, int blockStepX,
196 int blockStepY, BlockNormalisation norm)
197 {
198 super();
199 this.cellWidth = cellWidth;
200 this.cellHeight = cellHeight;
201 this.cellsPerBlockX = cellsPerBlockX;
202 this.cellsPerBlockY = cellsPerBlockY;
203 this.norm = norm;
204 this.blockStepX = blockStepX;
205 this.blockStepY = blockStepY;
206 }
207
208 @Override
209 public Histogram extract(WindowedHistogramExtractor binnedData, Rectangle region, Histogram output) {
210 final Histogram[][] cells = computeCells(binnedData, region);
211 final Histogram[][] blocks = computeBlocks(cells);
212
213 final int blockSize = blocks[0][0].values.length;
214 final int blockArea = cellsPerBlockX * cellsPerBlockY;
215
216 if (output == null || output.values.length != blocks[0].length * blocks.length * blockSize)
217 output = new Histogram(blocks[0].length * blocks.length * blockSize);
218
219 for (int j = 0, k = 0; j < blocks.length; j++) {
220 for (int i = 0; i < blocks[0].length; i++, k++) {
221 norm.normalise(blocks[j][i], blockArea);
222
223 System.arraycopy(blocks[j][i].values, 0, output.values, k * blockSize, blockSize);
224 }
225 }
226
227 return output;
228 }
229
230 private Histogram[][] computeBlocks(Histogram[][] cells) {
231 final int numBlocksX = 1 + (cells[0].length - cellsPerBlockX) / this.blockStepX;
232 final int numBlocksY = 1 + (cells.length - cellsPerBlockY) / this.blockStepY;
233 final Histogram[][] blocks = new Histogram[numBlocksY][numBlocksX];
234
235 for (int y = 0; y < numBlocksY; y++) {
236 for (int x = 0; x < numBlocksX; x++) {
237 final Histogram[] blockData = new Histogram[cellsPerBlockX * cellsPerBlockY];
238
239 for (int j = 0, k = 0; j < cellsPerBlockY; j++) {
240 for (int i = 0; i < cellsPerBlockX; i++) {
241 blockData[k++] = cells[y * blockStepY + j][x * blockStepX + i];
242 }
243 }
244
245 blocks[y][x] = new Histogram(blockData);
246 }
247 }
248 return blocks;
249 }
250
251 private Histogram[][] computeCells(WindowedHistogramExtractor binnedData, Rectangle region) {
252 final int numCellsX = (int) ((region.width + cellWidth / 2) / cellWidth);
253 final int numCellsY = (int) ((region.height + cellHeight / 2) / cellHeight);
254
255 final Histogram[][] cells = new Histogram[numCellsY][numCellsX];
256 for (int j = 0, y = (int) region.y; j < numCellsY; j++, y += cellHeight) {
257 for (int i = 0, x = (int) region.x; i < numCellsX; i++, x += cellWidth) {
258 cells[j][i] = binnedData.computeHistogram(x, y, cellWidth, cellHeight);
259 cells[j][i].normaliseL2();
260 }
261 }
262
263 return cells;
264 }
265 }