2 * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
4 * This file is part of LEA.
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
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
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/>.
25 @METHODDEFAULT("OUT<V,V<THIS,THIS<C,C<IN,C*,V*,THISLOC=THIS,RETURNLOC=OUT")
26 public class Classifier {
29 private ScanArea[] scanAreas;
32 private float[] possibilities_FaceYes;
34 private float[] possibilities_FaceNo;
36 private int possibilityFaceYes = 0;
38 private int possibilityFaceNo = 0;
40 public Classifier(int numScanAreas) {
41 this.scanAreas = new ScanArea[numScanAreas];
42 this.possibilities_FaceYes = new float[numScanAreas];
43 this.possibilities_FaceNo = new float[numScanAreas];
46 public void setScanArea(int idx, ScanArea area) {
47 scanAreas[idx] = area;
50 public void setPossibilitiesFaceYes(@DELEGATE float[] arr) {
51 this.possibilities_FaceYes = arr;
54 public void setPossibilityFaceYes(int v) {
55 this.possibilityFaceYes = v;
58 public void setPossibilitiesFaceNo(@DELEGATE float[] arr) {
59 this.possibilities_FaceNo = arr;
62 public void setPossibilityFaceNo(int v) {
63 this.possibilityFaceNo = v;
67 * Classifies an images region as face
71 * please be aware of the fact that the scanareas are scaled for use
72 * with 100x100 px images
75 * @return true if this region was classified as face, else false
77 public boolean classifyFace(@LOC("IN") IntegralImageData image, @LOC("IN") float scaleFactor,
78 @LOC("IN") int translationX, @LOC("IN") int translationY, @LOC("IN") float borderline) {
80 @LOC("V") long values[] = new long[this.scanAreas.length];
82 @LOC("V") float avg = 0f;
83 @LOC("V") int avgItems = 0;
84 for (@LOC("C") int i = 0; i < this.scanAreas.length; ++i) {
88 image.getIntegralAt(translationX + scanAreas[i].getToX(scaleFactor), translationY
89 + scanAreas[i].getToY(scaleFactor));
91 image.getIntegralAt(translationX + scanAreas[i].getFromX(scaleFactor), translationY
92 + scanAreas[i].getFromY(scaleFactor));
95 image.getIntegralAt(translationX + scanAreas[i].getToX(scaleFactor), translationY
96 + scanAreas[i].getFromY(scaleFactor));
98 image.getIntegralAt(translationX + scanAreas[i].getFromX(scaleFactor), translationY
99 + scanAreas[i].getToY(scaleFactor));
101 values[i] = (long) (values[i] / ((float) scanAreas[i].getSize(scaleFactor)));
102 avg = ((avgItems * avg) + values[i]) / (++avgItems);
104 // System.out.println("avg=" + avg);
106 // int amountYesNo = this.possibilityFaceNo + this.possibilityFaceYes;
108 // calculate the possibilites for face=yes and face=no with naive bayes
109 // P(Yes | M1 and ... and Mn) = P(Yes) * P(M1 | Yes) * ... * P(Mn | Yes) /xx
110 // P(No | M1 and ... and Mn) = P(No) * P(M1 | No) * ... * P(Mn | No) / xx
111 // as we just maximize the args we don't actually calculate the accurate
114 @LOC("OUT") float isFaceYes = 1.0f;// this.possibilityFaceYes /
115 // (float)amountYesNo;
116 @LOC("OUT") float isFaceNo = 1.0f;// this.possibilityFaceNo /
117 // (float)amountYesNo;
119 for (@LOC("C") int i = 0; i < this.scanAreas.length; ++i) {
120 @LOC("V") boolean bright = (values[i] >= avg);
121 isFaceYes *= (bright ? this.possibilities_FaceYes[i] : 1 - this.possibilities_FaceYes[i]);
122 isFaceNo *= (bright ? this.possibilities_FaceNo[i] : 1 - this.possibilities_FaceNo[i]);
124 // System.out.println("avg=" + avg + " yes=" + isFaceYes + " no=" +
127 return (isFaceYes >= isFaceNo && (isFaceYes / (isFaceYes + isFaceNo)) > borderline);
130 public ScanArea[] getScanAreas() {
131 return this.scanAreas;
134 public int getLearnedFacesYes() {
135 return this.possibilityFaceYes;
138 public int getLearnedFacesNo() {
139 return this.possibilityFaceNo;
142 public float getPossibility(int scanAreaID, boolean faceYes, boolean bright) {
144 return (bright ? this.possibilities_FaceYes[scanAreaID]
145 : 1 - this.possibilities_FaceYes[scanAreaID]);
147 return (bright ? this.possibilities_FaceNo[scanAreaID]
148 : 1 - this.possibilities_FaceNo[scanAreaID]);
152 public int compareTo(Classifier o) {
153 if (o.getScanAreas().length > this.getScanAreas().length) {
155 } else if (o.getScanAreas().length < this.getScanAreas().length) {
161 public String toString() {
163 @LOC("OUT") String str = "";
164 for (@LOC("C") int i = 0; i < scanAreas.length; i++) {
165 str += scanAreas[i].toString() + "\n";