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.analysis.algorithm;
31
32 import org.openimaj.image.FImage;
33 import org.openimaj.math.geometry.shape.Rectangle;
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49 public class SummedSqTiltAreaTable extends SummedSqAreaTable {
50
51
52
53 public FImage tiltSum;
54
55
56
57
58 public SummedSqTiltAreaTable() {
59 }
60
61
62
63
64
65
66
67
68 public SummedSqTiltAreaTable(FImage image) {
69 this(image, true);
70 }
71
72
73
74
75
76
77
78
79
80
81 public SummedSqTiltAreaTable(FImage image, boolean computeTilted) {
82 computeTable(image, computeTilted);
83 }
84
85 private void computeTable(FImage image, boolean computeTilted) {
86 if (computeTilted) {
87 computeRotSqSumIntegralImages(image);
88 } else {
89 computeSqSumIntegralImages(image);
90 }
91 }
92
93 protected void computeSqSumIntegralImages(FImage img) {
94 final int width = img.width;
95 final int height = img.height;
96
97 sum = new FImage(width + 1, height + 1);
98 sqSum = new FImage(width + 1, height + 1);
99
100 final float[][] sumData = sum.pixels;
101 final float[][] sqSumData = sqSum.pixels;
102
103 for (int y = 1; y <= height; y++) {
104 float rowSum = 0;
105 float rowSumSQ = 0;
106
107 final float[] row = img.pixels[y - 1];
108 for (int x = 1; x <= width; x++) {
109 final float pix = row[x - 1];
110
111 rowSum += pix;
112 rowSumSQ += pix * pix;
113
114 sumData[y][x] = sumData[y - 1][x] + rowSum;
115 sqSumData[y][x] = sqSumData[y - 1][x] + rowSumSQ;
116 }
117 }
118 }
119
120 protected final void computeRotSqSumIntegralImages(FImage image) {
121 final int width = image.width;
122 final int height = image.height;
123
124 sum = new FImage(width + 1, height + 1);
125 sqSum = new FImage(width + 1, height + 1);
126 tiltSum = new FImage(width + 2, height + 2);
127
128 final float[] buffer = new float[width];
129
130
131
132 if (height > 0) {
133 final float[] row = image.pixels[0];
134
135 float rowSum = 0;
136 float sqRowSum = 0;
137
138 for (int x = 1; x <= width; x++) {
139 final float gray = (row[x - 1]);
140
141 rowSum += gray;
142 sqRowSum += gray * gray;
143
144 sum.pixels[1][x] = rowSum;
145 buffer[x - 1] = tiltSum.pixels[1][x] = gray;
146 sqSum.pixels[1][x] = sqRowSum;
147 }
148 }
149
150
151 if (height > 1) {
152 final float[] row = image.pixels[1];
153
154 float rowSum = 0;
155 float sqRowSum = 0;
156
157 for (int x = 1; x < width; x++) {
158 final float gray = (row[x - 1]);
159
160 rowSum += gray;
161 sqRowSum += gray * gray;
162
163 sum.pixels[2][x] = sum.pixels[1][x] + rowSum;
164 sqSum.pixels[2][x] = sqSum.pixels[1][x] + sqRowSum;
165 tiltSum.pixels[2][x] = tiltSum.pixels[1][x - 1] + buffer[x - 1] + tiltSum.pixels[1][x + 1] + gray;
166 buffer[x - 1] = gray;
167 }
168
169
170 if (width > 0) {
171 final float gray = (row[width - 1]);
172
173 rowSum += gray;
174 sqRowSum += gray * gray;
175
176 sum.pixels[2][width] = sum.pixels[1][width] + rowSum;
177 sqSum.pixels[2][width] = sqSum.pixels[1][width] + sqRowSum;
178 tiltSum.pixels[2][width] = tiltSum.pixels[1][width - 1] + buffer[width - 1] + gray;
179 buffer[width - 1] = gray;
180 }
181 }
182
183 for (int y = 3; y <= height; y++) {
184 final float[] row = image.pixels[y - 1];
185
186 float rowSum = 0;
187 float sqRowSum = 0;
188
189 if (width > 0) {
190 final float gray = row[0];
191 rowSum += gray;
192 sqRowSum += gray * gray;
193
194 sum.pixels[y][1] = sum.pixels[y - 1][1] + rowSum;
195 sqSum.pixels[y][1] = sqSum.pixels[y - 1][1] + sqRowSum;
196 tiltSum.pixels[y][1] = tiltSum.pixels[y - 1][2] + buffer[0] + gray;
197 buffer[0] = gray;
198 }
199
200 for (int x = 2; x < width; x++) {
201 final float gray = row[x - 1];
202 rowSum += gray;
203 sqRowSum += gray * gray;
204
205 sum.pixels[y][x] = sum.pixels[y - 1][x] + rowSum;
206 sqSum.pixels[y][x] = sqSum.pixels[y - 1][x] + sqRowSum;
207 tiltSum.pixels[y][x] = tiltSum.pixels[y - 1][x - 1] + buffer[x - 1] + tiltSum.pixels[y - 1][x + 1]
208 - tiltSum.pixels[y - 2][x] + gray;
209 buffer[x - 1] = gray;
210 }
211
212 if (width > 0) {
213 final float gray = row[width - 1];
214 rowSum += gray;
215 sqRowSum += gray * gray;
216
217 sum.pixels[y][width] = sum.pixels[y - 1][width] + rowSum;
218 sqSum.pixels[y][width] = sqSum.pixels[y - 1][width] + sqRowSum;
219 tiltSum.pixels[y][width] = tiltSum.pixels[y - 1][width - 1] + buffer[width - 1] + gray;
220 buffer[width - 1] = gray;
221 }
222 }
223 }
224
225
226
227
228
229
230
231
232
233
234
235
236 public float calculateTiltedSumArea(int x, int y, int width, int height) {
237 final float p0 = tiltSum.pixels[y][x];
238 final float p1 = tiltSum.pixels[y + height][x - height];
239 final float p2 = tiltSum.pixels[y + width][x + width];
240 final float p3 = tiltSum.pixels[y + width + height][x + width - height];
241
242 return p0 - p1 - p2 + p3;
243 }
244
245
246
247
248
249
250
251
252
253 public float calculateTiltedSumArea(Rectangle r) {
254 return calculateTiltedSumArea(Math.round(r.x), Math.round(r.y), Math.round(r.width),
255 Math.round(r.height));
256 }
257
258
259
260
261
262
263
264
265 @Override
266 public void analyseImage(FImage image) {
267 computeTable(image, true);
268 }
269 }