changes: 1) fixes problems in the original EyeTracking benchmark 2) fix a bug in...
[IRC.git] / Robust / src / Benchmarks / SSJava / EyeTrackingInfer / ClassifierTree.java
index 01c2fe17d369f4b65e00d349f6e7b6801e31587e..dc150e1d1b1c6eed5c9b993e8d95700aeb61c45d 100644 (file)
@@ -14,7 +14,10 @@ import SSJava.PCLOC;
  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
  * details.
- * 
+ *   private Point readEyes( Image image,  Rectangle2D rect) {
+  EyeDetector ed = new EyeDetector(image, rect);
+ return ed.detectEye();
+ }
  * You should have received a copy of the GNU Lesser General Public License
  * along with LEA. If not, see <http://www.gnu.org/licenses/>.
  */
@@ -24,18 +27,38 @@ import SSJava.PCLOC;
  * @author Florian
  */
 
-public class ClassifierTree {
 
-  private Classifier classifiers[];
+public class ClassifierTree {
 
-  public ClassifierTree(int size) {
+  
+  private Classifier[] classifiers;
+  
+  double x;
+  
+  double y;
+  
+  double width;
+  
+  double height;
+
+  
+  int size;
+
+  
+  public ClassifierTree( int size) {
+    this.size = size;
     classifiers = new Classifier[size];
+    x = -1;
+    y = -1;
+    width = -1;
+    height = -1;
   }
 
-  public void addClassifier(int idx, Classifier c) {
+  public void addClassifier( int idx,  Classifier c) {
     classifiers[idx] = c;
   }
 
+  
   /**
    * Locates a face by searching radial starting at the last known position. If lastCoordinates are
    * null we simply start in the center of the image.
@@ -49,101 +72,123 @@ public class ClassifierTree {
    * @return an rectangle representing the actual face position on success or null if no face could
    *         be detected
    */
-
-  public Rectangle2D locateFaceRadial(Image smallImage, Rectangle2D lastCoordinates) {
-
-    IntegralImageData imageData = new IntegralImageData(smallImage);
-    float originalImageFactor = 1;
-
-    if (lastCoordinates == null) {
+  
+  public void locateFaceRadial( Image smallImage) {
+
+     double px = x;
+     double py = y;
+     double pwidth = width;
+     double pheight = height;
+
+    x = -1;
+    y = -1;
+    width = -1;
+    height = -1;
+
+     IntegralImageData imageData = new IntegralImageData(smallImage);
+     float originalImageFactor = 1;
+    if (px == -1) {
+      // if(true){
       // if we don't have a last coordinate we just begin in the center
-      int smallImageMaxDimension = Math.min(smallImage.getWidth(), smallImage.getHeight());
-      lastCoordinates =
-          new Rectangle2D((smallImage.getWidth() - smallImageMaxDimension) / 2.0,
-              (smallImage.getHeight() - smallImageMaxDimension) / 2.0, smallImageMaxDimension,
-              smallImageMaxDimension);
-      // System.out.println("lastCoordinates=" + lastCoordinates);
+       int smallImageMaxDimension = Math.min(smallImage.getWidth(), smallImage.getHeight());
+
+      px = (smallImage.getWidth() - smallImageMaxDimension) / 2.0;
+      py = (smallImage.getHeight() - smallImageMaxDimension) / 2.0;
+      pwidth = smallImageMaxDimension;
+      pheight = smallImageMaxDimension;
     } else {
       // first we have to scale the last coodinates back relative to the resized
       // image
-      lastCoordinates =
-          new Rectangle2D((lastCoordinates.getX() * (1 / originalImageFactor)),
-              (lastCoordinates.getY() * (1 / originalImageFactor)),
-              (lastCoordinates.getWidth() * (1 / originalImageFactor)),
-              (lastCoordinates.getHeight() * (1 / originalImageFactor)));
+      px = px * (1 / originalImageFactor);
+      py = py * (1 / originalImageFactor);
+      pwidth = pwidth * (1 / originalImageFactor);
+      pheight = pheight * (1 / originalImageFactor);
     }
 
-    float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
+
+     float startFactor = (float) (pwidth / 100.0f);
 
     // first we calculate the maximum scale factor for our 200x200 image
-    float maxScaleFactor = Math.min(imageData.getWidth() / 100f, imageData.getHeight() / 100f);
+     float maxScaleFactor = Math.min(imageData.getWidth() / 100f, imageData.getHeight() / 100f);
     // maxScaleFactor = 1.0f;
 
     // we simply won't recognize faces that are smaller than 40x40 px
-    float minScaleFactor = 0.5f;
+     float minScaleFactor = 0.5f;
 
-    float maxScaleDifference = Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor - startFactor));
+     float maxScaleDifference = Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor - startFactor));
 
     // border for faceYes-possibility must be greater that that
-    float maxBorder = 0.999f;
+     float maxBorder = 0.999f;
 
-    int startPosX = (int) lastCoordinates.getX();
-    int startPosY = (int) lastCoordinates.getX();
+     int startPosX = (int) px;
+     int startPosY = (int) py;
 
-    int loopidx = 0;
-    TERMINATE: for (float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
+     int loopidx = 0;
+    TERMINATE: for ( float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
         (factorDiff + sgn(factorDiff) * 0.1f) * -1 // we alternate between
                                                    // negative and positiv
                                                    // factors
     ) {
 
       if (++loopidx > 1000) {
-        return null;
+        px = -1;
+        py = -1;
+        pwidth = -1;
+        pheight = -1;
+        return;
       }
 
-      float factor = startFactor + factorDiff;
+       float factor = startFactor + factorDiff;
       if (factor > maxScaleFactor || factor < minScaleFactor)
         continue;
 
       // now we calculate the actualDimmension
-      int actualDimmension = (int) (100 * factor);
-      int maxX = imageData.getWidth() - actualDimmension;
-      int maxY = imageData.getHeight() - actualDimmension;
+       int actualDimmension = (int) (100 * factor);
+       int maxX = imageData.getWidth() - actualDimmension;
+       int maxY = imageData.getHeight() - actualDimmension;
 
-      int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
-      int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
+       int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
+       int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
 
-      int xidx = 0;
-      TERMINATE: for (float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
+       int xidx = 0;
+      TERMINATE: for ( float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
           (xDiff + sgn(xDiff) * 0.5f) * -1) {
 
         if (++xidx > 1000) {
-          return null;
+          px = -1;
+          py = -1;
+          pwidth = -1;
+          pheight = -1;
+          return;
         }
 
-        int xPos = Math.round((float) (startPosX + xDiff));
+         int xPos = Math.round((float) (startPosX + xDiff));
 
         if (xPos < 0 || xPos > maxX)
           continue;
 
-        int yidx = 0;
+         int yidx = 0;
         // yLines:
-        TERMINATE: for (float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
+        TERMINATE: for ( float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
             (yDiff + sgn(yDiff) * 0.5f) * -1) {
 
           if (++yidx > 1000) {
-            return null;
+            px = -1;
+            py = -1;
+            pwidth = -1;
+            pheight = -1;
+            return;
           }
 
-          int yPos = Math.round(startPosY + yDiff);
+           int yPos = Math.round(startPosY + yDiff);
           if (yPos < 0 || yPos > maxY)
             continue;
 
           // by now we should have a valid coordinate to process which we should
           // do now
-          boolean backToYLines = false;
-          for (int idx = 0; idx < classifiers.length; ++idx) {
-            float borderline = 0.8f + (idx / (classifiers.length - 1)) * (maxBorder - 0.8f);
+           boolean backToYLines = false;
+          for ( int idx = 0; idx < size; ++idx) {
+             float borderline = 0.8f + (idx / (size - 1)) * (maxBorder - 0.8f);
             if (!classifiers[idx].classifyFace(imageData, factor, xPos, yPos, borderline)) {
               backToYLines = true;
               break;
@@ -159,9 +204,11 @@ public class ClassifierTree {
             continue;
           }
 
-          Rectangle2D faceRect = new Rectangle2D(xPos * originalImageFactor, yPos * originalImageFactor, actualDimmension * originalImageFactor, actualDimmension * originalImageFactor);
-
-          return faceRect;
+          x = xPos * originalImageFactor;
+          y = yPos * originalImageFactor;
+          width = actualDimmension * originalImageFactor;
+          height = actualDimmension * originalImageFactor;
+          return;
 
         }
 
@@ -169,13 +216,46 @@ public class ClassifierTree {
 
     }
 
-    // System.out.println("Time: "+(System.currentTimeMillis()-timeStart)+"ms");
-    return null;
 
   }
 
-  private static int sgn(float value) {
+  
+  
+  private static int sgn( float value) {
     return (value < 0 ? -1 : (value > 0 ? +1 : 1));
   }
 
+  
+  public FaceAndEyePosition getEyePosition( Image image) {
+    if (image == null) {
+      return null;
+    }
+
+     float originalImageFactor = 1;
+
+    locateFaceRadial(image);
+
+    if (width > image.getWidth() || height > image.getHeight()) {
+      return null;
+    }
+
+     EyePosition eyePosition = null;
+
+    if (x != -1) {
+       EyeDetector ed = new EyeDetector(image, x, y, width, height);
+       Point point = ed.detectEye();
+      if (point != null) {
+        eyePosition = new EyePosition(point.getX(), point.getY());
+      }
+    }
+
+    System.out.println("eyePosition=" + eyePosition);
+
+     FaceAndEyePosition fep = new FaceAndEyePosition(x, y, width, height, eyePosition);
+
+
+    return fep;
+  }
+
+
 }