changes: 1) fixes problems in the original EyeTracking benchmark 2) fix a bug in...
[IRC.git] / Robust / src / Benchmarks / SSJava / EyeTracking / ClassifierTree.java
index fa69d23..3c7c94e 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(@LOC("IN") Image image, @LOC("IN") Rectangle2D rect) {
+ @LOC("OUT") 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/>.
  */
@@ -23,15 +26,33 @@ import SSJava.PCLOC;
  * 
  * @author Florian
  */
-@LATTICE("CS<C,C*")
+@LATTICE("C<CS,CS<CUR,CUR<PREV,PREV<SIZE,PREV*,C*,CUR*")
 @METHODDEFAULT("OUT<THIS,THIS<IN,THISLOC=THIS,RETURNLOC=OUT")
 public class ClassifierTree {
 
   @LOC("CS")
   private Classifier classifiers[];
 
-  public ClassifierTree(int size) {
+  @LOC("CUR")
+  double x;
+  @LOC("CUR")
+  double y;
+  @LOC("CUR")
+  double width;
+  @LOC("CUR")
+  double height;
+
+  @LOC("SIZE")
+  int size;
+
+  @LATTICE("THIS<IN,THISLOC=THIS")
+  public ClassifierTree(@LOC("IN") int size) {
+    this.size = size;
     classifiers = new Classifier[size];
+    x = -1;
+    y = -1;
+    width = -1;
+    height = -1;
   }
 
   public void addClassifier(@LOC("IN") int idx, @LOC("IN") Classifier c) {
@@ -39,120 +60,141 @@ public class ClassifierTree {
   }
 
   /**
-   * 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.
+   * 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.
    * <p>
-   * TODO: This method could quite possible be tweaked so that face recognition
-   * would be much faster
+   * TODO: This method could quite possible be tweaked so that face recognition would be much faster
    * 
    * @param image
    *          the image to process
    * @param lastCoordinates
    *          the last known coordinates or null if unknown
-   * @return an rectangle representing the actual face position on success or
-   *         null if no face could be detected
+   * @return an rectangle representing the actual face position on success or null if no face could
+   *         be detected
    */
   @LATTICE("OUT<CXY,CXY<THIS,THIS<V,V<IMG,IMG<C,C<IN,C*,V*,FACTOR*,CXY*,THISLOC=THIS,RETURNLOC=OUT,GLOBALLOC=IN")
-  @PCLOC("C")
-  public Rectangle2D locateFaceRadial(@LOC("IN") Image smallImage,
-      @LOC("THIS,ClassifierTree.C") Rectangle2D lastCoordinates) {
+  public void locateFaceRadial(@LOC("IN") Image smallImage) {
+
+    @LOC("THIS,ClassifierTree.CUR") double px = x;
+    @LOC("THIS,ClassifierTree.CUR") double py = y;
+    @LOC("THIS,ClassifierTree.CUR") double pwidth = width;
+    @LOC("THIS,ClassifierTree.CUR") double pheight = height;
+
+    x = -1;
+    y = -1;
+    width = -1;
+    height = -1;
 
     @LOC("IMG") IntegralImageData imageData = new IntegralImageData(smallImage);
     @LOC("IN") float originalImageFactor = 1;
-
-    if (lastCoordinates == null) {
+    if (px == -1) {
+      // if(true){
       // if we don't have a last coordinate we just begin in the center
-      @LOC("THIS,ClassifierTree.C") int smallImageMaxDimension =
+      @LOC("THIS,ClassifierTree.PREV") 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);
+
+      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);
     }
 
-    @LOC("THIS,ClassifierTree.C") float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
+
+    @LOC("THIS,ClassifierTree.CUR") float startFactor = (float) (pwidth / 100.0f);
 
     // first we calculate the maximum scale factor for our 200x200 image
-    @LOC("THIS,ClassifierTree.C") float maxScaleFactor =
+    @LOC("THIS,ClassifierTree.CUR") 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
-    @LOC("THIS,ClassifierTree.C") float minScaleFactor = 0.5f;
+    @LOC("THIS,ClassifierTree.CUR") float minScaleFactor = 0.5f;
 
-    @LOC("THIS,ClassifierTree.C") float maxScaleDifference =
+    @LOC("THIS,ClassifierTree.CUR") float maxScaleDifference =
         Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor - startFactor));
 
     // border for faceYes-possibility must be greater that that
-    @LOC("THIS,ClassifierTree.C") float maxBorder = 0.999f;
+    @LOC("THIS,ClassifierTree.CUR") float maxBorder = 0.999f;
 
-    @LOC("THIS,ClassifierTree.C") int startPosX = (int) lastCoordinates.getX();
-    @LOC("THIS,ClassifierTree.C") int startPosY = (int) lastCoordinates.getX();
+    @LOC("THIS,ClassifierTree.CUR") int startPosX = (int) px;
+    @LOC("THIS,ClassifierTree.CUR") int startPosY = (int) py;
 
-    @LOC("THIS,ClassifierTree.C") int loopidx = 0;
-    TERMINATE: for (@LOC("THIS,ClassifierTree.C") float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
+    @LOC("THIS,ClassifierTree.CUR") int loopidx = 0;
+    TERMINATE: for (@LOC("THIS,ClassifierTree.CUR") 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;
       }
 
-      @LOC("THIS,ClassifierTree.C") float factor = startFactor + factorDiff;
+      @LOC("THIS,ClassifierTree.CUR") float factor = startFactor + factorDiff;
       if (factor > maxScaleFactor || factor < minScaleFactor)
         continue;
 
       // now we calculate the actualDimmension
-      @LOC("THIS,ClassifierTree.C") int actualDimmension = (int) (100 * factor);
-      @LOC("THIS,ClassifierTree.C") int maxX = imageData.getWidth() - actualDimmension;
-      @LOC("THIS,ClassifierTree.C") int maxY = imageData.getHeight() - actualDimmension;
+      @LOC("THIS,ClassifierTree.CUR") int actualDimmension = (int) (100 * factor);
+      @LOC("THIS,ClassifierTree.CUR") int maxX = imageData.getWidth() - actualDimmension;
+      @LOC("THIS,ClassifierTree.CUR") int maxY = imageData.getHeight() - actualDimmension;
 
-      @LOC("THIS,ClassifierTree.C") int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
-      @LOC("THIS,ClassifierTree.C") int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
+      @LOC("THIS,ClassifierTree.CUR") int maxDiffX =
+          Math.max(Math.abs(startPosX - maxX), startPosX);
+      @LOC("THIS,ClassifierTree.CUR") int maxDiffY =
+          Math.max(Math.abs(startPosY - maxY), startPosY);
 
-      @LOC("CXY") int xidx = 0;
-      TERMINATE: for (@LOC("CXY") float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
+      @LOC("THIS,ClassifierTree.CUR") int xidx = 0;
+      TERMINATE: for (@LOC("THIS,ClassifierTree.CUR") 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;
         }
 
-        @LOC("CXY") int xPos = Math.round((float) (startPosX + xDiff));
+        @LOC("THIS,ClassifierTree.CUR") int xPos = Math.round((float) (startPosX + xDiff));
 
         if (xPos < 0 || xPos > maxX)
           continue;
 
-        @LOC("CXY") int yidx = 0;
+        @LOC("THIS,ClassifierTree.CUR") int yidx = 0;
         // yLines:
-        TERMINATE: for (@LOC("CXY") float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
+        TERMINATE: for (@LOC("THIS,ClassifierTree.CUR") 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;
           }
 
-          @LOC("CXY") int yPos = Math.round(startPosY + yDiff);
+          @LOC("THIS,ClassifierTree.CUR") 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
-          @LOC("CXY") boolean backToYLines = false;
-          for (@LOC("CXY") int idx = 0; idx < classifiers.length; ++idx) {
-            @LOC("CXY") float borderline =
-                0.8f + (idx / (classifiers.length - 1)) * (maxBorder - 0.8f);
+          @LOC("THIS,ClassifierTree.C") boolean backToYLines = false;
+          for (@LOC("THIS,ClassifierTree.CUR") int idx = 0; idx < size; ++idx) {
+            @LOC("THIS,ClassifierTree.CUR") float borderline =
+                0.8f + (idx / (size - 1)) * (maxBorder - 0.8f);
             if (!classifiers[idx].classifyFace(imageData, factor, xPos, yPos, borderline)) {
               backToYLines = true;
               break;
@@ -167,11 +209,12 @@ public class ClassifierTree {
           if (backToYLines) {
             continue;
           }
-          @LOC("OUT") 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;
 
         }
 
@@ -180,7 +223,7 @@ public class ClassifierTree {
     }
 
     // System.out.println("Time: "+(System.currentTimeMillis()-timeStart)+"ms");
-    return null;
+    // return null;
 
   }
 
@@ -190,4 +233,36 @@ public class ClassifierTree {
     return (value < 0 ? -1 : (value > 0 ? +1 : 1));
   }
 
+  @LATTICE("OUT<P,P<ED,ED<V,V<THIS,THIS<IN,V*,THISLOC=THIS,RETURNLOC=OUT,GLOBALLOC=IN")
+  public FaceAndEyePosition getEyePosition(@LOC("IN") Image image) {
+    if (image == null) {
+      return null;
+    }
+
+    @LOC("IN") float originalImageFactor = 1;
+
+    locateFaceRadial(image);
+
+    if (width > image.getWidth() || height > image.getHeight()) {
+      return null;
+    }
+
+    @LOC("OUT") EyePosition eyePosition = null;
+
+    if (x != -1) {
+      @LOC("ED") EyeDetector ed = new EyeDetector(image, x, y, width, height);
+      @LOC("P") Point point = ed.detectEye();
+      if (point != null) {
+        eyePosition = new EyePosition(point.getX(), point.getY());
+      }
+    }
+
+    System.out.println("eyePosition=" + eyePosition);
+
+    @LOC("OUT") FaceAndEyePosition fep = new FaceAndEyePosition(x, y, width, height, eyePosition);
+
+    return fep;
+  }
+
+
 }