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.saliency;
31
32 import java.util.Arrays;
33
34 import org.openimaj.citation.annotation.Reference;
35 import org.openimaj.citation.annotation.ReferenceType;
36 import org.openimaj.image.FImage;
37 import org.openimaj.image.processing.convolution.AverageBoxFilter;
38 import org.openimaj.image.processing.convolution.FConvolution;
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57 @Reference(
58 type = ReferenceType.Inproceedings,
59 author = { "Luo, Yiwen", "Tang, Xiaoou" },
60 title = "Photo and Video Quality Evaluation: Focusing on the Subject",
61 year = "2008",
62 booktitle = "Proceedings of the 10th European Conference on Computer Vision: Part III",
63 pages = { "386", "", "399" },
64 url = "http://dx.doi.org/10.1007/978-3-540-88690-7_29",
65 publisher = "Springer-Verlag",
66 series = "ECCV '08",
67 customData = {
68 "isbn", "978-3-540-88689-1",
69 "location", "Marseille, France",
70 "numpages", "14",
71 "doi", "10.1007/978-3-540-88690-7_29",
72 "acmid", "1478204",
73 "address", "Berlin, Heidelberg"
74 })
75 public class DepthOfFieldEstimator implements SaliencyMapGenerator<FImage> {
76 private static FConvolution DX_FILTER = new FConvolution(new float[][] { { 1, -1 } });
77 private static FConvolution DY_FILTER = new FConvolution(new float[][] { { 1 }, { -1 } });
78
79 protected int maxKernelSize = 50;
80 protected int kernelSizeStep = 1;
81 protected int nbins = 41;
82
83 protected int windowSize = 3;
84
85 protected float[][] xHistograms;
86 protected float[][] yHistograms;
87 private FImage map;
88
89
90
91
92
93
94
95
96
97
98
99
100
101 public DepthOfFieldEstimator(int maxKernelSize, int kernelSizeStep, int nbins, int windowSize) {
102 this.maxKernelSize = maxKernelSize;
103 this.kernelSizeStep = kernelSizeStep;
104 this.nbins = nbins;
105 this.windowSize = windowSize;
106 this.xHistograms = new float[maxKernelSize / kernelSizeStep][nbins];
107 this.yHistograms = new float[maxKernelSize / kernelSizeStep][nbins];
108 }
109
110
111
112
113
114 public DepthOfFieldEstimator() {
115 this.xHistograms = new float[maxKernelSize / kernelSizeStep][nbins];
116 this.yHistograms = new float[maxKernelSize / kernelSizeStep][nbins];
117 }
118
119 protected void clearHistograms() {
120 for (final float[] h : xHistograms)
121 Arrays.fill(h, 0);
122
123 for (final float[] h : yHistograms)
124 Arrays.fill(h, 0);
125 }
126
127
128
129
130
131
132
133
134 @Override
135 public void analyseImage(FImage image) {
136 clearHistograms();
137
138 for (int i = 0, j = 0; i < maxKernelSize; i += kernelSizeStep, j++) {
139 final FImage blurred = image.process(new AverageBoxFilter(i + 1, i + 1));
140 final FImage dx = blurred.process(DX_FILTER);
141 final FImage dy = blurred.process(DY_FILTER);
142
143 makeLogHistogram(xHistograms[j], dx);
144 makeLogHistogram(yHistograms[j], dy);
145 }
146
147 final FImage dx = image.process(DX_FILTER);
148 final FImage dy = image.process(DY_FILTER);
149 map = new FImage(image.width, image.height);
150 for (int y = 0; y < image.height; y++) {
151 for (int x = 0; x < image.width; x++) {
152 if (x == 0 || y == 0 || x == image.width - 1 || y == image.height - 1) {
153 map.pixels[y][x] = maxKernelSize;
154 } else {
155 int bestModel = 0;
156 double bestLL = calculatedLogLikelihood(x, y, dx, dy, 0);
157
158 for (int i = 1, j = 1; i < maxKernelSize; i += kernelSizeStep, j++) {
159 final double newLL = calculatedLogLikelihood(x, y, dx, dy, j);
160
161 if (newLL > bestLL) {
162 bestLL = newLL;
163 bestModel = i;
164 }
165 }
166
167 map.pixels[y][x] = bestModel;
168 }
169 }
170 }
171 }
172
173 private double calculatedLogLikelihood(int x, int y, FImage dx, FImage dy, int level) {
174 final int border = windowSize / 2;
175
176 double LL = 0;
177 for (int j = y - border; j <= y + border; j++) {
178 for (int i = x - border; i <= x + border; i++) {
179 final float vx = (dx.pixels[j][i] + 1) / 2;
180 int bx = (int) (vx * nbins);
181 if (bx >= nbins)
182 bx--;
183
184 final float vy = (dy.pixels[j][i] + 1) / 2;
185 int by = (int) (vy * nbins);
186 if (by >= nbins)
187 by--;
188
189 LL += xHistograms[level][bx] + yHistograms[level][by];
190 }
191 }
192 return LL;
193 }
194
195 private void makeLogHistogram(float[] h, FImage im) {
196 int sum = 0;
197 for (int y = 0; y < im.height; y++) {
198 for (int x = 0; x < im.width; x++) {
199 final float v = (im.pixels[y][x] + 1) / 2;
200
201 int bin = (int) (v * nbins);
202 if (bin >= nbins)
203 bin--;
204
205 h[bin]++;
206 sum++;
207 }
208 }
209
210 for (int i = 0; i < nbins; i++) {
211 if (h[i] == 0)
212 h[i] = 0.00000001f;
213
214 h[i] = (float) Math.log(h[i] / (double) sum);
215 }
216 }
217
218 @Override
219 public FImage getSaliencyMap() {
220 return map;
221 }
222 }