add eye tracking benchmark.
[IRC.git] / Robust / src / Benchmarks / SSJava / EyeTracking / Classifier.java
1 /*
2  * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
3  * 
4  * This file is part of LEA.
5  * 
6  * LEA is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU Lesser General Public License as published by the Free
8  * Software Foundation, either version 3 of the License, or (at your option) any
9  * later version.
10  * 
11  * LEA is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14  * details.
15  * 
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with LEA. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * 
22  * @author Florian
23  */
24 public class Classifier {
25
26   private ScanArea[] scanAreas;
27
28   // private float possibilityFace = 0f;
29   private float[] possibilities_FaceYes;
30   private float[] possibilities_FaceNo;
31   private int possibilityFaceYes = 0;
32   private int possibilityFaceNo = 0;
33
34   public static final long serialVersionUID = 5168971806943656945l;
35
36   public Classifier(int numScanAreas) {
37     this.scanAreas = new ScanArea[numScanAreas];
38     this.possibilities_FaceYes = new float[numScanAreas];
39     this.possibilities_FaceNo = new float[numScanAreas];
40   }
41
42   public void setScanArea(int idx, ScanArea area) {
43     scanAreas[idx] = area;
44   }
45
46   public void setPossibilitiesFaceYes(float[] arr) {
47     this.possibilities_FaceYes = arr;
48   }
49
50   public void setPossibilityFaceYes(int v) {
51     this.possibilityFaceYes = v;
52   }
53
54   public void setPossibilitiesFaceNo(float[] arr) {
55     this.possibilities_FaceNo = arr;
56   }
57
58   public void setPossibilityFaceNo(int v) {
59     this.possibilityFaceNo = v;
60   }
61
62   // public void learn(IntegralImageData image, boolean isFace) {
63   // long values[] = new long[this.scanAreas.length];
64   // //
65   // System.out.println("HERE:"+image.getIntegralAt(image.getDimension().width-1,
66   // // image.getDimension().height-1));
67   // // we assume the image is rectangular so we can simply use one side to
68   // // calculate
69   // // the scale factor
70   // float scaleFactor = image.getDimension().width / 100.0f;
71   //
72   // float avg = 0f;
73   // int avgItems = 0;
74   // for (int i = 0; i < this.scanAreas.length; ++i) {
75   // ScanArea scanArea = this.scanAreas[i];
76   // values[i] = 0l;
77   //
78   // values[i] += image.getIntegralAt(scanArea.getToX(scaleFactor),
79   // scanArea.getToY(scaleFactor));
80   // values[i] +=
81   // image.getIntegralAt(scanArea.getFromX(scaleFactor),
82   // scanArea.getFromY(scaleFactor));
83   //
84   // values[i] -=
85   // image.getIntegralAt(scanArea.getToX(scaleFactor),
86   // scanArea.getFromY(scaleFactor));
87   // values[i] -=
88   // image.getIntegralAt(scanArea.getFromX(scaleFactor),
89   // scanArea.getToY(scaleFactor));
90   //
91   // values[i] = (long) (values[i] / ((float) scanArea.getSize(scaleFactor)));
92   // avg = ((avgItems * avg) + values[i]) / (++avgItems);
93   // }
94   //
95   // if (isFace) {
96   // this.possibilityFaceYes++;
97   // } else {
98   // this.possibilityFaceNo++;
99   // }
100   // for (int i = 0; i < this.scanAreas.length; ++i) {
101   // boolean bright = (values[i] >= avg);
102   //
103   // if (isFace) {
104   // // here we change the possibility of P(Scanarea_N = (Bright | NotBright)
105   // // | Face=Yes)
106   // this.possibilities_FaceYes[i] =
107   // (((this.possibilityFaceYes - 1) * this.possibilities_FaceYes[i]) + (bright
108   // ? 0.999f
109   // : 0.001f)) / this.possibilityFaceYes;
110   // //
111   // System.out.println("P(Scannarea"+i+"=bright|Face=Yes) = "+this.possibilities_FaceYes[i]);
112   // //
113   // System.out.println("P(Scannarea"+i+"=dark|Face=Yes) = "+(1.0f-this.possibilities_FaceYes[i]));
114   // } else {
115   // // here we change the possibility of P(Scanarea_N = (Bright | NotBright)
116   // // | Face=No)
117   // this.possibilities_FaceNo[i] =
118   // (((this.possibilityFaceNo - 1) * this.possibilities_FaceNo[i]) + (bright ?
119   // 0.999f
120   // : 0.001f)) / this.possibilityFaceNo;
121   // //
122   // System.out.println("P(Scannarea"+i+"=bright|Face=No) = "+this.possibilities_FaceNo[i]);
123   // //
124   // System.out.println("P(Scannarea"+i+"=dark|Face=No) = "+(1.0f-this.possibilities_FaceNo[i]));
125   // }
126   //
127   // }
128   //
129   // // System.out.println("Average: "+avg);
130   // // System.out.println(this);
131   // }
132
133   /**
134    * Classifies an images region as face
135    * 
136    * @param image
137    * @param scaleFactor
138    *          please be aware of the fact that the scanareas are scaled for use
139    *          with 100x100 px images
140    * @param translationX
141    * @param translationY
142    * @return true if this region was classified as face, else false
143    */
144   // public boolean classifyFace(IntegralImageData image, float scaleFactor, int
145   // translationX,
146   // int translationY, float borderline) {
147   //
148   // long values[] = new long[this.scanAreas.length];
149   //
150   // float avg = 0f;
151   // int avgItems = 0;
152   // for (int i = 0; i < this.scanAreas.length; ++i) {
153   // ScanArea scanArea = this.scanAreas[i];
154   // values[i] = 0l;
155   //
156   // values[i] +=
157   // image.getIntegralAt(translationX + scanArea.getToX(scaleFactor),
158   // translationY + scanArea.getToY(scaleFactor));
159   // values[i] +=
160   // image.getIntegralAt(translationX + scanArea.getFromX(scaleFactor),
161   // translationY
162   // + scanArea.getFromY(scaleFactor));
163   //
164   // values[i] -=
165   // image.getIntegralAt(translationX + scanArea.getToX(scaleFactor),
166   // translationY + scanArea.getFromY(scaleFactor));
167   // values[i] -=
168   // image.getIntegralAt(translationX + scanArea.getFromX(scaleFactor),
169   // translationY
170   // + scanArea.getToY(scaleFactor));
171   //
172   // values[i] = (long) (values[i] / ((float) scanArea.getSize(scaleFactor)));
173   // avg = ((avgItems * avg) + values[i]) / (++avgItems);
174   // }
175   //
176   // // int amountYesNo = this.possibilityFaceNo + this.possibilityFaceYes;
177   //
178   // // calculate the possibilites for face=yes and face=no with naive bayes
179   // // P(Yes | M1 and ... and Mn) = P(Yes) * P(M1 | Yes) * ... * P(Mn | Yes)
180   // /xx
181   // // P(No | M1 and ... and Mn) = P(No) * P(M1 | No) * ... * P(Mn | No) / xx
182   // // as we just maximize the args we don't actually calculate the accurate
183   // // possibility
184   //
185   // float isFaceYes = 1.0f;// this.possibilityFaceYes / (float)amountYesNo;
186   // float isFaceNo = 1.0f;// this.possibilityFaceNo / (float)amountYesNo;
187   //
188   // for (int i = 0; i < this.scanAreas.length; ++i) {
189   // boolean bright = (values[i] >= avg);
190   // isFaceYes *= (bright ? this.possibilities_FaceYes[i] : 1 -
191   // this.possibilities_FaceYes[i]);
192   // isFaceNo *= (bright ? this.possibilities_FaceNo[i] : 1 -
193   // this.possibilities_FaceNo[i]);
194   // }
195   //
196   // return (isFaceYes >= isFaceNo && (isFaceYes / (isFaceYes + isFaceNo)) >
197   // borderline);
198   // }
199
200   public ScanArea[] getScanAreas() {
201     return this.scanAreas;
202   }
203
204   public int getLearnedFacesYes() {
205     return this.possibilityFaceYes;
206   }
207
208   public int getLearnedFacesNo() {
209     return this.possibilityFaceNo;
210   }
211
212   public float getPossibility(int scanAreaID, boolean faceYes, boolean bright) {
213     if (faceYes) {
214       return (bright ? this.possibilities_FaceYes[scanAreaID]
215           : 1 - this.possibilities_FaceYes[scanAreaID]);
216     } else {
217       return (bright ? this.possibilities_FaceNo[scanAreaID]
218           : 1 - this.possibilities_FaceNo[scanAreaID]);
219     }
220   }
221
222   public int compareTo(Classifier o) {
223     if (o.getScanAreas().length > this.getScanAreas().length) {
224       return -1;
225     } else if (o.getScanAreas().length < this.getScanAreas().length) {
226       return 1;
227     } else
228       return 0;
229   }
230
231   public String toString() {
232
233     String str = "";
234     for (int i = 0; i < scanAreas.length; i++) {
235       str += scanAreas[i].toString() + "\n";
236     }
237
238     return str;
239
240   }
241   // @Override
242   // public String toString() {
243   // StringBuilder sb = new StringBuilder();
244   // sb.append("Classifier [ScanAreas: " + this.scanAreas.length);
245   // int yesNo = this.possibilityFaceYes + this.possibilityFaceNo;
246   // sb.append(String.format("|Yes: %3.2f| No:%3.2f] (",
247   // (this.possibilityFaceYes / (float) yesNo) * 100.0f,
248   // (this.possibilityFaceNo / (float) yesNo) * 100.0f));
249   // for (int i = 0; i < this.scanAreas.length; ++i) {
250   // sb.append(String.format("[%3d|Yes: %3.2f| No: %3.2f], ", i + 1,
251   // (this.possibilities_FaceYes[i] * 100.0f), (this.possibilities_FaceNo[i] *
252   // 100.0f)));
253   // }
254   // sb.append(")");
255   //
256   // return sb.toString();
257   // }
258
259   /**
260    * Generates a new set of classifiers each with more ScanAreas than the last
261    * classifier. You can specifiy the amount of classifiers you want to generate
262    * 
263    * @param amount
264    *          amount of classifiers to create
265    * @param startAmountScanAreas
266    *          the start amount of scanAreas - if your first classifiers should
267    *          contain 3 items you should give 3 here
268    * @param incAmountScanAreas
269    *          the amount of which the scanAreas should increase - a simple 2
270    *          will increase them by 2 every step
271    * @return a List of classifiers
272    */
273   // public static List<Classifier> generateNewClassifiers(int amount, int
274   // startAmountScanAreas,
275   // float incAmountScanAreas) {
276   // List<Classifier> classifiers = new ArrayList<Classifier>();
277   //
278   // int maxDim = 40;
279   // Random random = new Random(System.currentTimeMillis());
280   // double maxSpace = 2 * Math.PI * Math.pow(50, 2);
281   //
282   // for (int i = 0; i < amount; ++i) {
283   // // we create an odd amount of ScanAreas starting with 1 (3, 5, 7, ...)
284   // int scanAreaAmount = startAmountScanAreas + (int)
285   // Math.pow(incAmountScanAreas, i);// +
286   // // ((i)*incAmountScanAreas+1);
287   //
288   // int scanAreaSize =
289   // randomInt(random, scanAreaAmount * 20, (int) Math.min(maxDim * maxDim,
290   // maxSpace))
291   // / scanAreaAmount;
292   // // System.out.println("scanAreaSize = "+scanAreaSize);
293   //
294   // List<ScanArea> scanAreas = new ArrayList<ScanArea>();
295   //
296   // for (int j = 0; j < scanAreaAmount; ++j) {
297   //
298   // int counter = 0;
299   // ScanArea scanArea = null;
300   // do {
301   // // new the width has the first choice
302   // int minWidth = (int) Math.ceil(scanAreaSize / (float) maxDim);
303   //
304   // int scanAreaWidth = randomInt(random, minWidth, Math.min(maxDim,
305   // scanAreaSize / 2));
306   // int scanAreaHeight = (int) Math.ceil(scanAreaSize / (float) scanAreaWidth);
307   //
308   // int radius =
309   // randomInt(random, 5, Math.min(50 - scanAreaHeight / 2, 50 - scanAreaWidth /
310   // 2));
311   // double angle = random.nextFloat() * 2 * Math.PI;
312   //
313   // int posX = (int) (50 + Math.cos(angle) * radius) - (scanAreaWidth / 2);
314   // int posY = (int) (50 + Math.sin(angle) * radius) - (scanAreaHeight / 2);
315   //
316   // // System.out.println("[Angle: "+(angle /
317   // // (Math.PI*2)*180)+" | radius: "+radius+"]");
318   // //
319   // System.out.println("Area"+j+" is "+posX+", "+posY+" ("+scanAreaWidth+" x "+scanAreaHeight+" = "+((scanAreaWidth*scanAreaHeight))+")");
320   //
321   // // now we get random position for this area
322   // scanArea = new ScanArea(posX, posY, scanAreaWidth, scanAreaHeight);
323   //
324   // counter++;
325   // } while (scanAreas.contains(scanArea) && counter < 30);
326   //
327   // if (counter == 30) {
328   // j -= 1;
329   // continue;
330   // }
331   //
332   // scanAreas.add(scanArea);
333   // }
334   //
335   // Classifier classifier = new Classifier(scanAreas.toArray(new ScanArea[0]));
336   // classifiers.add(classifier);
337   // }
338   //
339   // return classifiers;
340   // }
341
342   // private static int randomInt(Random random, int from, int to) {
343   // if (to - from <= 0)
344   // to = from + 1;
345   // return from + random.nextInt(to - from);
346   // }
347   //
348   // public static List<Classifier> getDefaultClassifier() {
349   // List<Classifier> classifier = new ArrayList<Classifier>();
350   //
351   // classifier.add(new Classifier(new ScanArea(30, 30, 30, 30), new
352   // ScanArea(15, 8, 15, 82),
353   // new ScanArea(75, 8, 15, 82)));
354   //
355   // return classifier;
356   // }
357
358 }