add PCLOC annotations. all three benchmarks are type-checked now.
[IRC.git] / Robust / src / Benchmarks / SSJava / EyeTracking / ClassifierTree.java
index 8c3dfffef7ad8dc697a67bae018b6ffbdb426357..fa69d23518a887ea5c49c6272a7e52c9a4516002 100644 (file)
@@ -1,3 +1,5 @@
+import SSJava.PCLOC;
+
 /*
  * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
  * 
  * 
  * @author Florian
  */
+@LATTICE("CS<C,C*")
+@METHODDEFAULT("OUT<THIS,THIS<IN,THISLOC=THIS,RETURNLOC=OUT")
 public class ClassifierTree {
 
-  private ArrayList classifiers;
+  @LOC("CS")
+  private Classifier classifiers[];
 
-  public ClassifierTree() {
-    classifiers = new ArrayList();
+  public ClassifierTree(int size) {
+    classifiers = new Classifier[size];
   }
 
-  public void addClassifier(Classifier c) {
-    classifiers.add(c);
+  public void addClassifier(@LOC("IN") int idx, @LOC("IN") Classifier c) {
+    classifiers[idx] = c;
   }
 
-  // public static BufferedImage resizeImageFittingInto(BufferedImage image, int
-  // dimension) {
-  //
-  // int newHeight = 0;
-  // int newWidth = 0;
-  // float factor = 0;
-  // if (image.getWidth() > image.getHeight()) {
-  // factor = dimension / (float) image.getWidth();
-  // newWidth = dimension;
-  // newHeight = (int) (factor * image.getHeight());
-  // } else {
-  // factor = dimension / (float) image.getHeight();
-  // newHeight = dimension;
-  // newWidth = (int) (factor * image.getWidth());
-  // }
-  //
-  // if (factor > 1) {
-  // BufferedImageOp op = new
-  // ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
-  // BufferedImage tmpImage = op.filter(image, null);
-  //
-  // return tmpImage;
-  // }
-  //
-  // BufferedImage resizedImage = new BufferedImage(newWidth, newHeight,
-  // BufferedImage.TYPE_INT_RGB);
-  //
-  // Graphics2D g2D = resizedImage.createGraphics();
-  // g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
-  // RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-  //
-  // g2D.drawImage(image, 0, 0, newWidth - 1, newHeight - 1, 0, 0,
-  // image.getWidth() - 1,
-  // image.getHeight() - 1, null);
-  //
-  // BufferedImageOp op = new
-  // ColorConvertOp(ColorSpace.getInstance(ColorSpace.CS_GRAY), null);
-  // BufferedImage tmpImage = op.filter(resizedImage, null);
-  //
-  // return tmpImage;
-  // }
-  //
-  // /**
-  // * Image should have 100x100px and should be in b/w
-  // *
-  // * @param image
-  // */
-  // public void learn(BufferedImage image, boolean isFace) {
-  // IntegralImageData imageData = new IntegralImageData(image);
-  // for (Classifier classifier : this.classifiers) {
-  // classifier.learn(imageData, isFace);
-  // }
-  // }
-  //
-  // public int getLearnedFacesYes() {
-  // return this.classifiers.get(0).getLearnedFacesYes();
-  // }
-  //
-  // public int getLearnedFacesNo() {
-  // return this.classifiers.get(0).getLearnedFacesNo();
-  // }
-
-  /**
-   * Locates a face by linear iteration through all probable face positions
-   * 
-   * @deprecated use locateFaceRadial instead for improved performance
-   * @param image
-   * @return an rectangle representing the actual face position on success or
-   *         null if no face could be detected
-   */
-  // public Rectangle2D locateFace(BufferedImage image) {
-  // long timeStart = System.currentTimeMillis();
-  //
-  // int resizeTo = 600;
-  //
-  // BufferedImage smallImage = resizeImageFittingInto(image, resizeTo);
-  // IntegralImageData imageData = new IntegralImageData(smallImage);
-  //
-  // float factor = image.getWidth() / (float) smallImage.getWidth();
-  //
-  // int maxIterations = 0;
-  //
-  // // first we calculate the maximum scale factor for our 200x200 image
-  // float maxScaleFactor = Math.min(imageData.getWidth() / 100f,
-  // imageData.getHeight() / 100f);
-  //
-  // // we simply won't recognize faces that are smaller than 40x40 px
-  // float minScaleFactor = 0.5f;
-  //
-  // // border for faceYes-possibility must be greater that that
-  // float maxBorder = 0.999f;
-  //
-  // for (float scale = maxScaleFactor; scale > minScaleFactor; scale -= 0.25) {
-  // int actualDimension = (int) (scale * 100);
-  // int borderX = imageData.getWidth() - actualDimension;
-  // int borderY = imageData.getHeight() - actualDimension;
-  // for (int x = 0; x <= borderX; ++x) {
-  // yLines: for (int y = 0; y <= borderY; ++y) {
-  //
-  // for (int iterations = 0; iterations < this.classifiers.size();
-  // ++iterations) {
-  // Classifier classifier = this.classifiers.get(iterations);
-  //
-  // float borderline =
-  // 0.8f + (iterations / this.classifiers.size() - 1) * (maxBorder - 0.8f);
-  // if (iterations > maxIterations)
-  // maxIterations = iterations;
-  // if (!classifier.classifyFace(imageData, scale, x, y, borderline)) {
-  // continue yLines;
-  // }
-  // }
-  //
-  // // if we reach here we have a face recognized because our image went
-  // // through all
-  // // classifiers
-  //
-  // Rectangle2D faceRect =
-  // new Rectangle2D.Float(x * factor, y * factor, actualDimension * factor,
-  // actualDimension * factor);
-  //
-  // System.out.println("Time: " + (System.currentTimeMillis() - timeStart) +
-  // "ms");
-  // return faceRect;
-  //
-  // }
-  // }
-  // }
-  //
-  // return null;
-  // }
-
   /**
    * 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.
@@ -178,20 +52,23 @@ public class ClassifierTree {
    * @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 Rectangle2D locateFaceRadial(Image smallImage, Rectangle2D lastCoordinates) {
-
-    IntegralImageData imageData = new IntegralImageData(smallImage);
-    float originalImageFactor = 1;
+    @LOC("IMG") IntegralImageData imageData = new IntegralImageData(smallImage);
+    @LOC("IN") float originalImageFactor = 1;
 
     if (lastCoordinates == null) {
       // if we don't have a last coordinate we just begin in the center
-      int smallImageMaxDimension = Math.min(smallImage.getWidth(), smallImage.getHeight());
+      @LOC("THIS,ClassifierTree.C") 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);
+      // System.out.println("lastCoordinates=" + lastCoordinates);
     } else {
       // first we have to scale the last coodinates back relative to the resized
       // image
@@ -202,72 +79,87 @@ public class ClassifierTree {
               (lastCoordinates.getHeight() * (1 / originalImageFactor)));
     }
 
-    float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
+    @LOC("THIS,ClassifierTree.C") float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
 
     // first we calculate the maximum scale factor for our 200x200 image
-    float maxScaleFactor = Math.min(imageData.getWidth() / 100f, imageData.getHeight() / 100f);
+    @LOC("THIS,ClassifierTree.C") 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;
+    @LOC("THIS,ClassifierTree.C") float minScaleFactor = 0.5f;
 
-    float maxScaleDifference =
+    @LOC("THIS,ClassifierTree.C") 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;
+    @LOC("THIS,ClassifierTree.C") float maxBorder = 0.999f;
 
-    int startPosX = (int) lastCoordinates.getX();
-    int startPosY = (int) lastCoordinates.getX();
+    @LOC("THIS,ClassifierTree.C") int startPosX = (int) lastCoordinates.getX();
+    @LOC("THIS,ClassifierTree.C") int startPosY = (int) lastCoordinates.getX();
 
-    for (float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
+    @LOC("THIS,ClassifierTree.C") int loopidx = 0;
+    TERMINATE: for (@LOC("THIS,ClassifierTree.C") float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference; factorDiff =
         (factorDiff + sgn(factorDiff) * 0.1f) * -1 // we alternate between
                                                    // negative and positiv
                                                    // factors
     ) {
 
-      float factor = startFactor + factorDiff;
-//      System.out.println("factor=" + factor);
+      if (++loopidx > 1000) {
+        return null;
+      }
+
+      @LOC("THIS,ClassifierTree.C") 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;
+      @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;
 
-      int maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
-      int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
+      @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);
 
-      for (float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
+      @LOC("CXY") int xidx = 0;
+      TERMINATE: for (@LOC("CXY") float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
           (xDiff + sgn(xDiff) * 0.5f) * -1) {
-        int xPos = Math.round((float) (startPosX + xDiff));
+
+        if (++xidx > 1000) {
+          return null;
+        }
+
+        @LOC("CXY") int xPos = Math.round((float) (startPosX + xDiff));
+
         if (xPos < 0 || xPos > maxX)
           continue;
 
+        @LOC("CXY") int yidx = 0;
         // yLines:
-        for (float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
+        TERMINATE: for (@LOC("CXY") float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
             (yDiff + sgn(yDiff) * 0.5f) * -1) {
-          int yPos = Math.round(startPosY + yDiff);
+
+          if (++yidx > 1000) {
+            return null;
+          }
+
+          @LOC("CXY") 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 iterations = 0; iterations < classifiers.size(); ++iterations) {
-            Classifier classifier = (Classifier) classifiers.get(iterations);
-
-            float borderline = 0.8f + (iterations / (classifiers.size() - 1)) * (maxBorder - 0.8f);
-            if (!classifier.classifyFace(imageData, factor, xPos, yPos, borderline)) {
-//              System.out.println("continue yLines; ");
+          @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);
+            if (!classifiers[idx].classifyFace(imageData, factor, xPos, yPos, borderline)) {
               backToYLines = true;
               break;
-              // continue yLines;              
+              // continue yLines;
             }
           }
 
-          
           // if we reach here we have a face recognized because our image went
           // through all
           // classifiers
@@ -275,7 +167,7 @@ public class ClassifierTree {
           if (backToYLines) {
             continue;
           }
-          Rectangle2D faceRect =
+          @LOC("OUT") Rectangle2D faceRect =
               new Rectangle2D(xPos * originalImageFactor, yPos * originalImageFactor,
                   actualDimmension * originalImageFactor, actualDimmension * originalImageFactor);
 
@@ -292,156 +184,9 @@ public class ClassifierTree {
 
   }
 
-  // public Rectangle2D locateFaceRadial(BufferedImage image, Rectangle2D
-  // lastCoordinates) {
-  //
-  // int resizeTo = 600;
-  //
-  // BufferedImage smallImage = resizeImageFittingInto(image, resizeTo);
-  // float originalImageFactor = image.getWidth() / (float)
-  // smallImage.getWidth();
-  // IntegralImageData imageData = new IntegralImageData(smallImage);
-  //
-  // if (lastCoordinates == null) {
-  // // 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.Float((smallImage.getWidth() - smallImageMaxDimension) /
-  // 2.0f,
-  // (smallImage.getHeight() - smallImageMaxDimension) / 2.0f,
-  // smallImageMaxDimension,
-  // smallImageMaxDimension);
-  // } else {
-  // // first we have to scale the last coodinates back relative to the resized
-  // // image
-  // lastCoordinates =
-  // new Rectangle2D.Float((float) (lastCoordinates.getX() * (1 /
-  // originalImageFactor)),
-  // (float) (lastCoordinates.getY() * (1 / originalImageFactor)),
-  // (float) (lastCoordinates.getWidth() * (1 / originalImageFactor)),
-  // (float) (lastCoordinates.getHeight() * (1 / originalImageFactor)));
-  // }
-  //
-  // float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
-  //
-  // // first we calculate the maximum scale factor for our 200x200 image
-  // 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 maxScaleDifference =
-  // Math.max(Math.abs(maxScaleFactor - startFactor), Math.abs(minScaleFactor -
-  // startFactor));
-  //
-  // // border for faceYes-possibility must be greater that that
-  // float maxBorder = 0.999f;
-  //
-  // int startPosX = (int) lastCoordinates.getX();
-  // int startPosY = (int) lastCoordinates.getX();
-  //
-  // for (float factorDiff = 0.0f; Math.abs(factorDiff) <= maxScaleDifference;
-  // factorDiff =
-  // (factorDiff + sgn(factorDiff) * 0.1f) * -1 // we alternate between
-  // // negative and positiv
-  // // factors
-  // ) {
-  //
-  // 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 maxDiffX = Math.max(Math.abs(startPosX - maxX), startPosX);
-  // int maxDiffY = Math.max(Math.abs(startPosY - maxY), startPosY);
-  //
-  // for (float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
-  // (xDiff + sgn(xDiff) * 0.5f) * -1) {
-  // int xPos = Math.round(startPosX + xDiff);
-  // if (xPos < 0 || xPos > maxX)
-  // continue;
-  //
-  // yLines: for (float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
-  // (yDiff + sgn(yDiff) * 0.5f) * -1) {
-  // 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
-  // for (int iterations = 0; iterations < this.classifiers.size();
-  // ++iterations) {
-  // Classifier classifier = this.classifiers.get(iterations);
-  //
-  // float borderline =
-  // 0.8f + (iterations / (this.classifiers.size() - 1)) * (maxBorder - 0.8f);
-  //
-  // if (!classifier.classifyFace(imageData, factor, xPos, yPos, borderline)) {
-  // continue yLines;
-  // }
-  // }
-  //
-  // // if we reach here we have a face recognized because our image went
-  // // through all
-  // // classifiers
-  //
-  // Rectangle2D faceRect =
-  // new Rectangle2D.Float(xPos * originalImageFactor, yPos *
-  // originalImageFactor,
-  // actualDimmension * originalImageFactor, actualDimmension *
-  // originalImageFactor);
-  //
-  // return faceRect;
-  //
-  // }
-  //
-  // }
-  //
-  // }
-  //
-  // //
-  // System.out.println("Time: "+(System.currentTimeMillis()-timeStart)+"ms");
-  // return null;
-  //
-  // }
-
-  // public List<Classifier> getClassifiers() {
-  // return new ArrayList<Classifier>(this.classifiers);
-  // }
-  //
-  // public static void saveToXml(OutputStream out, ClassifierTree tree) throws
-  // IOException {
-  // PrintWriter writer = new PrintWriter(new OutputStreamWriter(out, "UTF-8"));
-  // writer.write(xStream.toXML(tree));
-  // writer.close();
-  // }
-  //
-  // public static ClassifierTree loadFromXml(InputStream in) throws IOException
-  // {
-  // Reader reader = new InputStreamReader(in, "UTF-8");
-  // StringBuilder sb = new StringBuilder();
-  //
-  // char[] buffer = new char[1024];
-  // int read = 0;
-  // do {
-  // read = reader.read(buffer);
-  // if (read > 0) {
-  // sb.append(buffer, 0, read);
-  // }
-  // } while (read > -1);
-  // reader.close();
-  //
-  // return (ClassifierTree) xStream.fromXML(sb.toString());
-  // }
-
-  private static int sgn(float value) {
+  @LATTICE("OUT<IN,OUT<P,P<THIS,THISLOC=THIS,RETURNLOC=OUT")
+  @PCLOC("P")
+  private static int sgn(@LOC("IN") float value) {
     return (value < 0 ? -1 : (value > 0 ? +1 : 1));
   }