* @param translationY
* @return true if this region was classified as face, else false
*/
- // public boolean classifyFace(IntegralImageData image, float scaleFactor, int
- // translationX,
- // int translationY, float borderline) {
- //
- // long values[] = new long[this.scanAreas.length];
- //
- // float avg = 0f;
- // int avgItems = 0;
- // for (int i = 0; i < this.scanAreas.length; ++i) {
- // ScanArea scanArea = this.scanAreas[i];
- // values[i] = 0l;
- //
- // values[i] +=
- // image.getIntegralAt(translationX + scanArea.getToX(scaleFactor),
- // translationY + scanArea.getToY(scaleFactor));
- // values[i] +=
- // image.getIntegralAt(translationX + scanArea.getFromX(scaleFactor),
- // translationY
- // + scanArea.getFromY(scaleFactor));
- //
- // values[i] -=
- // image.getIntegralAt(translationX + scanArea.getToX(scaleFactor),
- // translationY + scanArea.getFromY(scaleFactor));
- // values[i] -=
- // image.getIntegralAt(translationX + scanArea.getFromX(scaleFactor),
- // translationY
- // + scanArea.getToY(scaleFactor));
- //
- // values[i] = (long) (values[i] / ((float) scanArea.getSize(scaleFactor)));
- // avg = ((avgItems * avg) + values[i]) / (++avgItems);
- // }
- //
- // // int amountYesNo = this.possibilityFaceNo + this.possibilityFaceYes;
- //
- // // calculate the possibilites for face=yes and face=no with naive bayes
- // // P(Yes | M1 and ... and Mn) = P(Yes) * P(M1 | Yes) * ... * P(Mn | Yes)
- // /xx
- // // P(No | M1 and ... and Mn) = P(No) * P(M1 | No) * ... * P(Mn | No) / xx
- // // as we just maximize the args we don't actually calculate the accurate
- // // possibility
- //
- // float isFaceYes = 1.0f;// this.possibilityFaceYes / (float)amountYesNo;
- // float isFaceNo = 1.0f;// this.possibilityFaceNo / (float)amountYesNo;
- //
- // for (int i = 0; i < this.scanAreas.length; ++i) {
- // boolean bright = (values[i] >= avg);
- // isFaceYes *= (bright ? this.possibilities_FaceYes[i] : 1 -
- // this.possibilities_FaceYes[i]);
- // isFaceNo *= (bright ? this.possibilities_FaceNo[i] : 1 -
- // this.possibilities_FaceNo[i]);
- // }
- //
- // return (isFaceYes >= isFaceNo && (isFaceYes / (isFaceYes + isFaceNo)) >
- // borderline);
- // }
+ public boolean classifyFace(IntegralImageData image, float scaleFactor, int translationX,
+ int translationY, float borderline) {
+
+ long values[] = new long[this.scanAreas.length];
+
+ float avg = 0f;
+ int avgItems = 0;
+ for (int i = 0; i < this.scanAreas.length; ++i) {
+ ScanArea scanArea = this.scanAreas[i];
+ values[i] = 0l;
+
+ values[i] +=
+ image.getIntegralAt(translationX + scanArea.getToX(scaleFactor),
+ translationY + scanArea.getToY(scaleFactor));
+ values[i] +=
+ image.getIntegralAt(translationX + scanArea.getFromX(scaleFactor), translationY
+ + scanArea.getFromY(scaleFactor));
+
+ values[i] -=
+ image.getIntegralAt(translationX + scanArea.getToX(scaleFactor),
+ translationY + scanArea.getFromY(scaleFactor));
+ values[i] -=
+ image.getIntegralAt(translationX + scanArea.getFromX(scaleFactor), translationY
+ + scanArea.getToY(scaleFactor));
+
+ values[i] = (long) (values[i] / ((float) scanArea.getSize(scaleFactor)));
+ avg = ((avgItems * avg) + values[i]) / (++avgItems);
+ }
+
+ // int amountYesNo = this.possibilityFaceNo + this.possibilityFaceYes;
+
+ // calculate the possibilites for face=yes and face=no with naive bayes
+ // P(Yes | M1 and ... and Mn) = P(Yes) * P(M1 | Yes) * ... * P(Mn | Yes) /xx
+ // P(No | M1 and ... and Mn) = P(No) * P(M1 | No) * ... * P(Mn | No) / xx
+ // as we just maximize the args we don't actually calculate the accurate
+ // possibility
+
+ float isFaceYes = 1.0f;// this.possibilityFaceYes / (float)amountYesNo;
+ float isFaceNo = 1.0f;// this.possibilityFaceNo / (float)amountYesNo;
+
+ for (int i = 0; i < this.scanAreas.length; ++i) {
+ boolean bright = (values[i] >= avg);
+ isFaceYes *= (bright ? this.possibilities_FaceYes[i] : 1 - this.possibilities_FaceYes[i]);
+ isFaceNo *= (bright ? this.possibilities_FaceNo[i] : 1 - this.possibilities_FaceNo[i]);
+ }
+
+ return (isFaceYes >= isFaceNo && (isFaceYes / (isFaceYes + isFaceNo)) > borderline);
+ }
public ScanArea[] getScanAreas() {
return this.scanAreas;
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
-import java.awt.RenderingHints;
-import java.awt.color.ColorSpace;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.BufferedImageOp;
-import java.awt.image.ColorConvertOp;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
/**
*
* @author Florian
*/
public class ClassifierTree {
- private List<Classifier> classifiers;
- private static XStream xStream = new XStream(new DomDriver());
+ private ArrayList classifiers;
- static {
- xStream.alias("ClassifierTree", ClassifierTree.class);
- xStream.alias("Classifier", Classifier.class);
- xStream.alias("ScanArea", ScanArea.class);
+ public ClassifierTree() {
+ classifiers = new ArrayList();
}
- public ClassifierTree(List<Classifier> classifier) {
- this.classifiers = new ArrayList<Classifier>(classifier);
- Collections.sort(this.classifiers);
+ public void addClassifier(Classifier c) {
+ classifiers.add(c);
}
- @Override
- public String toString() {
- StringBuilder sb = new StringBuilder();
- sb.append("ClassifierTree {\n");
- for (Classifier classifier : this.classifiers) {
- sb.append(classifier.toString());
- sb.append('\n');
- }
- sb.append("}\n");
- return sb.toString();
- }
-
- 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();
- }
+ // 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
* @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;
- }
+ // 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
* @return an rectangle representing the actual face position on success or
* null if no face could be detected
*/
- public Rectangle2D locateFaceRadial(BufferedImage image, Rectangle2D lastCoordinates) {
- int resizeTo = 600;
+ public Rectangle2D locateFaceRadial(Image smallImage, Rectangle2D lastCoordinates) {
- BufferedImage smallImage = resizeImageFittingInto(image, resizeTo);
- float originalImageFactor = image.getWidth() / (float) smallImage.getWidth();
IntegralImageData imageData = new IntegralImageData(smallImage);
+ 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());
lastCoordinates =
- new Rectangle2D.Float((smallImage.getWidth() - smallImageMaxDimension) / 2.0f,
- (smallImage.getHeight() - smallImageMaxDimension) / 2.0f, smallImageMaxDimension,
+ new Rectangle2D((smallImage.getWidth() - smallImageMaxDimension) / 2.0,
+ (smallImage.getHeight() - smallImageMaxDimension) / 2.0, 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)));
+ new Rectangle2D((lastCoordinates.getX() * (1 / originalImageFactor)),
+ (lastCoordinates.getY() * (1 / originalImageFactor)),
+ (lastCoordinates.getWidth() * (1 / originalImageFactor)),
+ (lastCoordinates.getHeight() * (1 / originalImageFactor)));
}
float startFactor = (float) (lastCoordinates.getWidth() / 100.0f);
for (float xDiff = 0.1f; Math.abs(xDiff) <= maxDiffX; xDiff =
(xDiff + sgn(xDiff) * 0.5f) * -1) {
- int xPos = Math.round(startPosX + xDiff);
+ int xPos = Math.round((float) (startPosX + xDiff));
if (xPos < 0 || xPos > maxX)
continue;
- yLines: for (float yDiff = 0.1f; Math.abs(yDiff) <= maxDiffY; yDiff =
+ // 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)
// 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);
+ boolean backToYLines = false;
+ for (int iterations = 0; iterations < classifiers.size(); ++iterations) {
+ Classifier classifier = (Classifier) classifiers.get(iterations);
- float borderline =
- 0.8f + (iterations / (this.classifiers.size() - 1)) * (maxBorder - 0.8f);
+ float borderline = 0.8f + (iterations / (classifiers.size() - 1)) * (maxBorder - 0.8f);
if (!classifier.classifyFace(imageData, factor, xPos, yPos, borderline)) {
- continue yLines;
+ backToYLines = true;
+ break;
+ // continue yLines;
}
}
// through all
// classifiers
+ if (backToYLines) {
+ continue;
+ }
+
Rectangle2D faceRect =
- new Rectangle2D.Float(xPos * originalImageFactor, yPos * originalImageFactor,
+ new Rectangle2D(xPos * originalImageFactor, yPos * originalImageFactor,
actualDimmension * originalImageFactor, actualDimmension * originalImageFactor);
return faceRect;
}
- 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());
- }
+ // 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) {
return (value < 0 ? -1 : (value > 0 ? +1 : 1));
+import Analysis.SSJava.Location;
+
/*
* Copyright 2009 (c) Florian Frankenberger (darkblue.de)
*
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
-
/**
* Representing an eyes deviation
*
* @author Florian Frankenberger
*/
-public enum Deviation {
- LEFT_UP(+1, -1),
- UP(0, -1),
- RIGHT_UP(-1, -1),
- LEFT(+1, 0),
- NONE(0, 0),
- RIGHT(-1, 0),
- LEFT_DOWN(+1, +1),
- DOWN(0, +1),
- RIGHT_DOWN(-1, +1);
-
- int directionX, directionY;
- Deviation(int directionX, int directionY) {
- this.directionX = directionX;
- this.directionY = directionY;
- }
-
- private boolean concurs(int directionX, int directionY) {
- return (directionX == this.directionX && directionY == this.directionY);
- }
-
-
- public static Deviation getDirectionFor(int directionX, int directionY) {
- for (Deviation direction: Deviation.values()) {
- if (direction.concurs(directionX, directionY)) {
- return direction;
- }
- }
-
- return null;
- }
+public class Deviation {
+
+ int directionX, directionY;
+ String direction;
+
+
+ public Deviation(String direction, int directionX, int directionY) {
+ this.directionX = directionX;
+ this.directionY = directionY;
+ this.direction = direction;
}
+
+ public boolean equals(Object o) {
+ if (!(o instanceof Deviation)) {
+ return false;
+ }
+
+ Deviation dev = (Deviation) o;
+ if (dev.directionX == directionX && dev.directionY == directionY) {
+ return true;
+ }
+
+ return false;
+ }
+
+}
* along with LEA. If not, see <http://www.gnu.org/licenses/>.\r
*/\r
\r
-\r
-import java.awt.geom.Rectangle2D;\r
-\r
/**\r
* No description given.\r
* \r
*/\r
public class DeviationScanner {\r
\r
- private StaticSizeArrayList<EyePosition> eyePositions = new StaticSizeArrayList<EyePosition>(3);\r
- \r
- public DeviationScanner() {\r
- }\r
-\r
- public void addEyePosition(EyePosition eyePosition) {\r
- eyePositions.add(eyePosition);\r
- }\r
- \r
- public Deviation scanForDeviation(Rectangle2D faceRect) {\r
- Deviation deviation = Deviation.NONE;\r
- if (eyePositions.size() >= 3) {\r
- double deviationX = 0;\r
- double deviationY = 0;\r
- \r
- EyePosition lastEyePosition = null;\r
- for (int i = 0; i < 3; ++i) {\r
- EyePosition eyePosition = this.eyePositions.get(i);\r
- if (lastEyePosition != null) {\r
- deviationX += (eyePosition.getX() - lastEyePosition.getX());\r
- deviationY += (eyePosition.getY() - lastEyePosition.getY());\r
- }\r
- lastEyePosition = eyePosition; \r
- }\r
- \r
- final double deviationPercentX = 0.04;\r
- final double deviationPercentY = 0.04;\r
- \r
- deviationX /= faceRect.getWidth();\r
- deviationY /= faceRect.getWidth();\r
- \r
- int deviationAbsoluteX = 0;\r
- int deviationAbsoluteY = 0;\r
- if (deviationX > deviationPercentX) deviationAbsoluteX = 1;\r
- if (deviationX < -deviationPercentX) deviationAbsoluteX = -1;\r
- if (deviationY > deviationPercentY) deviationAbsoluteY = 1;\r
- if (deviationY < -deviationPercentY) deviationAbsoluteY = -1;\r
- \r
- deviation = Deviation.getDirectionFor(deviationAbsoluteX, deviationAbsoluteY);\r
- if (deviation != Deviation.NONE) this.eyePositions.clear();\r
- //System.out.println(String.format("%.2f%% | %.2f%% => %d and %d >>> %s", deviationX*100, deviationY*100, deviationAbsoluteX, deviationAbsoluteY, deviation.toString()));\r
- \r
- }\r
- \r
- return deviation;\r
- }\r
- \r
- public void clear() {\r
- System.out.println("CLEAR");\r
- this.eyePositions.clear();\r
- }\r
+ private EyePosition eyePositions[];\r
+\r
+ private static final Deviation NONE = new Deviation("NONE", 0, 0);\r
+\r
+ public DeviationScanner() {\r
+ eyePositions = new EyePosition[3];\r
+ }\r
+\r
+ public void addEyePosition(EyePosition eyePosition) {\r
+\r
+ for (int i = eyePositions.length - 2; i >= 0; i--) {\r
+ eyePositions[i + 1] = eyePositions[i];\r
+ }\r
+ eyePositions[0] = eyePosition;\r
+ }\r
+\r
+ public Deviation scanForDeviation(Rectangle2D faceRect) {\r
+ Deviation deviation = NONE;\r
+ if (eyePositions.length >= 3) {\r
+ double deviationX = 0;\r
+ double deviationY = 0;\r
+\r
+ EyePosition lastEyePosition = null;\r
+ for (int i = 0; i < 3; ++i) {\r
+ EyePosition eyePosition = this.eyePositions[i];\r
+ if (lastEyePosition != null) {\r
+ deviationX += (eyePosition.getX() - lastEyePosition.getX());\r
+ deviationY += (eyePosition.getY() - lastEyePosition.getY());\r
+ }\r
+ lastEyePosition = eyePosition;\r
+ }\r
+\r
+ final double deviationPercentX = 0.04;\r
+ final double deviationPercentY = 0.04;\r
+\r
+ deviationX /= faceRect.getWidth();\r
+ deviationY /= faceRect.getWidth();\r
+\r
+ int deviationAbsoluteX = 0;\r
+ int deviationAbsoluteY = 0;\r
+ if (deviationX > deviationPercentX)\r
+ deviationAbsoluteX = 1;\r
+ if (deviationX < -deviationPercentX)\r
+ deviationAbsoluteX = -1;\r
+ if (deviationY > deviationPercentY)\r
+ deviationAbsoluteY = 1;\r
+ if (deviationY < -deviationPercentY)\r
+ deviationAbsoluteY = -1;\r
+\r
+ deviation = getDirectionFor(deviationAbsoluteX, deviationAbsoluteY);\r
+ if (deviation != NONE) {\r
+ eyePositions = new EyePosition[3];\r
+ }\r
+ // System.out.println(String.format("%.2f%% | %.2f%% => %d and %d >>> %s",\r
+ // deviationX*100, deviationY*100, deviationAbsoluteX, deviationAbsoluteY,\r
+ // deviation.toString()));\r
+\r
+ }\r
+\r
+ return deviation;\r
+ }\r
+\r
+ public static Deviation getDirectionFor(int directionX, int directionY) {\r
+\r
+ // for (Deviation direction : Deviation.values()) {\r
+ // if (direction.concurs(directionX, directionY)) {\r
+ // return direction;\r
+ // }\r
+ // }\r
+ return null;\r
+ }\r
+\r
+ public void clear() {\r
+ System.out.println("CLEAR");\r
+ // this.eyePositions.clear();\r
+ }\r
+\r
+ // LEFT_UP(+1, -1), UP(0, -1), RIGHT_UP(-1, -1), LEFT(+1, 0), NONE(0, 0),\r
+ // RIGHT(-1, 0), LEFT_DOWN(\r
+ // +1, +1), DOWN(0, +1), RIGHT_DOWN(-1, +1);\r
+ //\r
+\r
}\r
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
-
-import java.awt.Point;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-import java.awt.image.PixelGrabber;
-
/**
* No description given.
*
*/
class EyeDetector {
- private int width;
- private int height;
- private int[] pixelBuffer;
+ private int width;
+ private int height;
+ private int[] pixelBuffer;
- double percent;
+ double percent;
- public EyeDetector(BufferedImage image, Rectangle2D faceRect) {
+ public EyeDetector(Image image, Rectangle2D faceRect) {
- percent = 0.15*faceRect.getWidth();
- faceRect = new Rectangle2D.Double(
- faceRect.getX()+ percent,
- faceRect.getY()+ percent,
- faceRect.getWidth() - percent,
- faceRect.getHeight() - 2*percent
- );
-
- width = (int)faceRect.getWidth() / 2;
- height = (int)faceRect.getHeight() / 2;
- pixelBuffer = new int[width*height];
- PixelGrabber pg = new PixelGrabber(
- image,
- (int)faceRect.getX(), (int)faceRect.getY(),
- width, height,
- pixelBuffer, 0, width);
+ percent = 0.15 * faceRect.getWidth();
+ faceRect =
+ new Rectangle2D(faceRect.getX() + percent, faceRect.getY() + percent, faceRect.getWidth()
+ - percent, faceRect.getHeight() - 2 * percent);
- try {
- pg.grabPixels();
- } catch (InterruptedException ie) {}
+ width = (int) faceRect.getWidth() / 2;
+ height = (int) faceRect.getHeight() / 2;
+ pixelBuffer = new int[width * height];
+
+ for (int y = (int) faceRect.getY(); y < faceRect.getY() + height; y++) {
+ for (int x = (int) faceRect.getX(); x < faceRect.getX() + width; x++) {
+ pixelBuffer[(y * width) + x] = (int) image.getPixel(x, y);
+ }
}
- public Point detectEye() {
- Point eyePosition = null;
- float brightness = 255f;
+ }
- for (int y = 0; y < height; ++y) {
- for (int x = 0; x < width; ++x) {
- final int position = y*width + x;
- final int[] color = new int[] { (pixelBuffer[position] & 0xFF0000) >> 16, (pixelBuffer[position] & 0x00FF00) >> 8, pixelBuffer[position] & 0x0000FF };
- final float acBrightness = getBrightness(color);
+ public Point detectEye() {
+ Point eyePosition = null;
+ float brightness = 255f;
- if (acBrightness < brightness) {
- eyePosition = new Point(x + (int)percent, y + (int)percent);
- brightness = acBrightness;
- }
- }
- }
+ for (int y = 0; y < height; ++y) {
+ for (int x = 0; x < width; ++x) {
+ final int position = y * width + x;
+ final int[] color =
+ new int[] { (pixelBuffer[position] & 0xFF0000) >> 16,
+ (pixelBuffer[position] & 0x00FF00) >> 8, pixelBuffer[position] & 0x0000FF };
+ final float acBrightness = getBrightness(color);
- return eyePosition;
+ if (acBrightness < brightness) {
+ eyePosition = new Point(x + (int) percent, y + (int) percent);
+ brightness = acBrightness;
+ }
+ }
}
- private static float getBrightness(int[] color) {
- int min = Math.min(Math.min(color[0], color[1]), color[2]);
- int max = Math.max(Math.max(color[0], color[1]), color[2]);
+ return eyePosition;
+ }
- return 0.5f * (max + min);
- }
+ private static float getBrightness(int[] color) {
+ int min = Math.min(Math.min(color[0], color[1]), color[2]);
+ int max = Math.max(Math.max(color[0], color[1]), color[2]);
+
+ return 0.5f * (max + min);
+ }
}
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
-package de.darkblue.lea.model;
-
-import java.awt.Point;
-import java.awt.geom.Rectangle2D;
/**
* No description given.
return this.y;
}
- public Deviation getDeviation(EyePosition oldEyePosition) {
- if (oldEyePosition == null) return Deviation.NONE;
-
- //first we check if the faceRects are corresponding
- double widthChange = (this.faceRect.getWidth() - oldEyePosition.faceRect.getWidth()) / this.faceRect.getWidth();
- if (widthChange > 0.1) return Deviation.NONE;
-
- int maxDeviationX = (int)Math.round(this.faceRect.getWidth() / 4f);
- int maxDeviationY = (int)Math.round(this.faceRect.getWidth() / 8f);
- int minDeviation = (int)Math.round(this.faceRect.getWidth() / 16f);
-
- int deviationX = Math.abs(x - oldEyePosition.x);
- int directionX = sgn(x - oldEyePosition.x);
- if (deviationX < minDeviation || deviationX > maxDeviationX) directionX = 0;
-
- int deviationY = Math.abs(y - oldEyePosition.y);
- int directionY = sgn(y - oldEyePosition.y);
- if (deviationY < minDeviation || deviationY > maxDeviationY) directionY = 0;
-
- double deviationXPercent = deviationX / this.faceRect.getWidth();
- double deviationYPercent = deviationY / this.faceRect.getWidth();
-
- System.out.println(String.format("devX: %.2f | devY: %.2f", deviationXPercent*100f, deviationYPercent*100f));
- return Deviation.getDirectionFor(directionX, directionY);
- }
+// public Deviation getDeviation(EyePosition oldEyePosition) {
+// if (oldEyePosition == null) return Deviation.NONE;
+//
+// //first we check if the faceRects are corresponding
+// double widthChange = (this.faceRect.getWidth() - oldEyePosition.faceRect.getWidth()) / this.faceRect.getWidth();
+// if (widthChange > 0.1) return Deviation.NONE;
+//
+// int maxDeviationX = (int)Math.round(this.faceRect.getWidth() / 4f);
+// int maxDeviationY = (int)Math.round(this.faceRect.getWidth() / 8f);
+// int minDeviation = (int)Math.round(this.faceRect.getWidth() / 16f);
+//
+// int deviationX = Math.abs(x - oldEyePosition.x);
+// int directionX = sgn(x - oldEyePosition.x);
+// if (deviationX < minDeviation || deviationX > maxDeviationX) directionX = 0;
+//
+// int deviationY = Math.abs(y - oldEyePosition.y);
+// int directionY = sgn(y - oldEyePosition.y);
+// if (deviationY < minDeviation || deviationY > maxDeviationY) directionY = 0;
+//
+// double deviationXPercent = deviationX / this.faceRect.getWidth();
+// double deviationYPercent = deviationY / this.faceRect.getWidth();
+//
+// System.out.println(String.format("devX: %.2f | devY: %.2f", deviationXPercent*100f, deviationYPercent*100f));
+// return Deviation.getDirectionFor(directionX, directionY);
+// }
private static int sgn(int i) {
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
-package de.darkblue.lea.model;
-
-import java.awt.geom.Rectangle2D;
-
/**
* No description given.
*
*/
public class FaceAndEyePosition {
- private Rectangle2D facePosition;
- private EyePosition eyePosition;
+ private Rectangle2D facePosition;
+ private EyePosition eyePosition;
- public FaceAndEyePosition(Rectangle2D facePosition, EyePosition eyePosition) {
- this.facePosition = facePosition;
- this.eyePosition = eyePosition;
- }
+ public FaceAndEyePosition(Rectangle2D facePosition, EyePosition eyePosition) {
+ this.facePosition = facePosition;
+ this.eyePosition = eyePosition;
+ }
- public Rectangle2D getFacePosition() {
- return this.facePosition;
- }
+ public Rectangle2D getFacePosition() {
+ return this.facePosition;
+ }
- public EyePosition getEyePosition() {
- return this.eyePosition;
- }
+ public EyePosition getEyePosition() {
+ return this.eyePosition;
+ }
}
+++ /dev/null
-/*
- * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
- *
- * This file is part of LEA.
- *
- * LEA is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * LEA is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with LEA. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.geom.Rectangle2D;
-import java.awt.image.BufferedImage;
-
-/**
- *
- * @author Florian
- */
-class FaceInfoPanel extends InfoPanel {
-
- private static final long serialVersionUID = 453216951714787407L;
-
- public FaceInfoPanel() {
- super(
- "Face Detection",
- new String[] {
- "noface0.png",
- "noface1.png"
- },
- 2,
- 100,
- 100);
- this.setFace(null, null);
- }
-
- public void setFace(BufferedImage image, Rectangle2D faceRect) {
-
- BufferedImage faceRectImage = null;
- if (image != null && faceRect != null) {
- int width = (int)faceRect.getWidth();
- int height = (int)faceRect.getHeight();
-
- faceRectImage = new BufferedImage(width,
- height, BufferedImage.TYPE_INT_RGB);
-
- Graphics2D g2D = faceRectImage.createGraphics();
- g2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-
- g2D.drawImage(image, 0, 0, width, height, (int)faceRect.getX(), (int)faceRect.getY(), (int)faceRect.getX() + width, (int)faceRect.getY() + height, null);
-
- }
- this.setImage(faceRectImage);
- }
-
-}
--- /dev/null
+public class Image {
+
+ int width;
+ int height;
+ long pixel[][];
+
+ public Image(int width, int height) {
+ this.width = width;
+ this.height = height;
+ pixel = new long[width][height];
+ }
+
+ public void setPixel(int x, int y, long p) {
+ pixel[x][y] = p;
+ }
+
+ public long getPixel(int x, int y) {
+ return pixel[x][y];
+ }
+
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return height;
+ }
+
+}
--- /dev/null
+public class ImageReader {
+ public ImageReader() {
+ }
+
+ public Image readImage(String file) {
+
+ FileInputStream fs = new FileInputStream(file);
+ int bflen = 14; // 14 byte BITMAPFILEHEADER
+ byte bf[] = new byte[bflen];
+ // fs.read(bf,0,bflen);
+ fs.read(bf);
+ int bilen = 40; // 40-byte BITMAPINFOHEADER
+ byte bi[] = new byte[bilen];
+ // fs.read(bi,0,bilen);
+ fs.read(bi);
+ // Interperet data.
+ int nsize =
+ (((int) bf[5] & 0xff) << 24) | (((int) bf[4] & 0xff) << 16) | (((int) bf[3] & 0xff) << 8)
+ | (int) bf[2] & 0xff;
+ // System.out.println("File type is :" + (char) bf[0] + (char) bf[1]);
+ // System.out.println("Size of file is :" + nsize);
+ int nbisize =
+ (((int) bi[3] & 0xff) << 24) | (((int) bi[2] & 0xff) << 16) | (((int) bi[1] & 0xff) << 8)
+ | (int) bi[0] & 0xff;
+ // System.out.println("Size of bitmapinfoheader is :" + nbisize);
+ int nwidth =
+ (((int) bi[7] & 0xff) << 24) | (((int) bi[6] & 0xff) << 16) | (((int) bi[5] & 0xff) << 8)
+ | (int) bi[4] & 0xff;
+// System.out.println("Width is :" + nwidth);
+ int nheight =
+ (((int) bi[11] & 0xff) << 24) | (((int) bi[10] & 0xff) << 16) | (((int) bi[9] & 0xff) << 8)
+ | (int) bi[8] & 0xff;
+// System.out.println("Height is :" + nheight);
+ int nplanes = (((int) bi[13] & 0xff) << 8) | (int) bi[12] & 0xff;
+ // System.out.println("Planes is :" + nplanes);
+ int nbitcount = (((int) bi[15] & 0xff) << 8) | (int) bi[14] & 0xff;
+ // System.out.println("BitCount is :" + nbitcount);
+ // Look for non-zero values to indicate compression
+ int ncompression =
+ (((int) bi[19]) << 24) | (((int) bi[18]) << 16) | (((int) bi[17]) << 8) | (int) bi[16];
+// System.out.println("Compression is :" + ncompression);
+ int nsizeimage =
+ (((int) bi[23] & 0xff) << 24) | (((int) bi[22] & 0xff) << 16)
+ | (((int) bi[21] & 0xff) << 8) | (int) bi[20] & 0xff;
+// System.out.println("SizeImage is :" + nsizeimage);
+
+ int nxpm =
+ (((int) bi[27] & 0xff) << 24) | (((int) bi[26] & 0xff) << 16)
+ | (((int) bi[25] & 0xff) << 8) | (int) bi[24] & 0xff;
+ // System.out.println("X-Pixels per meter is :" + nxpm);
+ int nypm =
+ (((int) bi[31] & 0xff) << 24) | (((int) bi[30] & 0xff) << 16)
+ | (((int) bi[29] & 0xff) << 8) | (int) bi[28] & 0xff;
+ // System.out.println("Y-Pixels per meter is :" + nypm);
+ int nclrused =
+ (((int) bi[35] & 0xff) << 24) | (((int) bi[34] & 0xff) << 16)
+ | (((int) bi[33] & 0xff) << 8) | (int) bi[32] & 0xff;
+ // System.out.println("Colors used are :" + nclrused);
+ int nclrimp =
+ (((int) bi[39] & 0xff) << 24) | (((int) bi[38] & 0xff) << 16)
+ | (((int) bi[37] & 0xff) << 8) | (int) bi[36] & 0xff;
+ // System.out.println("Colors important are :" + nclrimp);
+
+ int ndata[];
+
+ Image image = new Image(nwidth, nheight);
+
+ if (nbitcount == 24) {
+ // No Palatte data for 24-bit format but scan lines are
+ // padded out to even 4-byte boundaries.
+ int npad = (nsizeimage / nheight) - nwidth * 3;
+ ndata = new int[(nheight * nwidth) + 4];
+ byte brgb[] = new byte[(nwidth + npad) * 3 * nheight];
+ // fs.read (brgb, 0, (nwidth + npad) * 3 * nheight);
+ fs.read(brgb);
+ int nindex = 0;
+ for (int j = 0; j < nheight; j++) {
+ for (int i = 0; i < nwidth; i++) {
+ // ndata[nwidth * (nheight - j - 1) + i] =
+ // (255 & 0xff) << 24 | (((int) brgb[nindex + 2] & 0xff) << 16)
+ // | (((int) brgb[nindex + 1] & 0xff) << 8) | (int) brgb[nindex] &
+ // 0xff;
+ // System.out.println("Encoded Color at (" + i + "," + j + ")is:" +
+ // brgb + " (R,G,B)= ("
+ // + ((int) (brgb[nindex + 2]) & 0xff) + "," + ((int) brgb[nindex + 1]
+ // & 0xff) + ","
+ // + ((int) brgb[nindex] & 0xff) + ")");
+ int ta =
+ ((3 * ((int) (brgb[nindex + 2]) & 0xff) + 6 * ((int) brgb[nindex + 1] & 0xff) + ((int) brgb[nindex] & 0xff))) / 10;
+ ndata[nwidth * (nheight - j - 1) + i + 4] = ta;
+ nindex += 3;
+ image.setPixel(i, j, ta);
+ }
+ nindex += npad;
+ }
+ // image = createImage
+ // ( new MemoryImageSource (nwidth, nheight,
+ // ndata, 0, nwidth));
+
+ } else if (nbitcount == 8) {
+ // Have to determine the number of colors, the clrsused
+ // parameter is dominant if it is greater than zero. If
+ // zero, calculate colors based on bitsperpixel.
+ int nNumColors = 0;
+ if (nclrused > 0) {
+ nNumColors = nclrused;
+ } else {
+ nNumColors = (1 & 0xff) << nbitcount;
+ }
+ System.out.println("The number of Colors is" + nNumColors);
+ // Some bitmaps do not have the sizeimage field calculated
+ // Ferret out these cases and fix 'em.
+ if (nsizeimage == 0) {
+ nsizeimage = ((((nwidth * nbitcount) + 31) & 31) >> 3);
+ nsizeimage *= nheight;
+ System.out.println("nsizeimage (backup) is" + nsizeimage);
+ }
+ // Read the palatte colors.
+ int npalette[] = new int[nNumColors];
+ byte bpalette[] = new byte[nNumColors * 4];
+ // fs.read (bpalette, 0, nNumColors*4);
+ fs.read(bpalette);
+ int nindex8 = 0;
+ for (int n = 0; n < nNumColors; n++) {
+ npalette[n] =
+ (255 & 0xff) << 24 | (((int) bpalette[nindex8 + 2] & 0xff) << 16)
+ | (((int) bpalette[nindex8 + 1] & 0xff) << 8) | (int) bpalette[nindex8] & 0xff;
+ // System.out.println ("Palette Color "+n
+ // +" is:"+npalette[n]+" (res,R,G,B)= (" +((int)(bpalette[nindex8+3]) &
+ // 0xff)+"," +((int)(bpalette[nindex8+2]) & 0xff)+","
+ // +((int)bpalette[nindex8+1]&0xff)+","
+ // +((int)bpalette[nindex8]&0xff)+")");
+
+ nindex8 += 4;
+ }
+ // Read the image data (actually indices into the palette)
+ // Scan lines are still padded out to even 4-byte
+ // boundaries.
+ int npad8 = (nsizeimage / nheight) - nwidth;
+ // System.out.println("nPad is:" + npad8);
+ // int ndata8[] = new int[nwidth * nheight];
+ ndata = new int[(nwidth * nheight) + 4];
+ byte bdata[] = new byte[(nwidth + npad8) * nheight];
+ // fs.read (bdata, 0, (nwidth+npad8)*nheight);
+ fs.read(bdata);
+ nindex8 = 0;
+ for (int j8 = 0; j8 < nheight; j8++) {
+ for (int i8 = 0; i8 < nwidth; i8++) {
+ ndata[nwidth * (nheight - j8 - 1) + i8 + 4] = npalette[((int) bdata[nindex8] & 0xff)];
+ image.setPixel(i8, j8, npalette[((int) bdata[nindex8] & 0xff)]);
+ // System.out.println("Encoded Color at (" + i8 + "," + j8 + ")is: "
+ // + ndata[nwidth * (nheight - j8 - 1) + i8 + 4]);
+ nindex8++;
+ }
+ nindex8 += npad8;
+ }
+ // image = createImage ( new MemoryImageSource (nwidth, nheight,
+ // ndata8, 0, nwidth));
+ } else {
+ System.out.println("Not a 24-bit or 8-bit Windows Bitmap, aborting...");
+ // image = (Image)null;
+ }
+ fs.close();
+
+ // ndata[0] = nheight;
+ // ndata[1] = nwidth;
+ // ndata[2] = nheight * nwidth;
+ // ndata[3] = 2;
+
+ return image;
+ // return ndata;
+
+ }
+
+}
\ No newline at end of file
+++ /dev/null
-/*
- * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
- *
- * This file is part of LEA.
- *
- * LEA is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * LEA is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with LEA. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-import java.awt.BasicStroke;
-import java.awt.Color;
-import java.awt.Graphics;
-import java.awt.Graphics2D;
-import java.awt.RenderingHints;
-import java.awt.image.BufferedImage;
-import java.io.IOException;
-import java.io.InputStream;
-import javax.imageio.ImageIO;
-import javax.swing.JPanel;
-
-/**
- *
- * @author Florian
- */
-abstract class InfoPanel extends JPanel {
-
- private static final long serialVersionUID = 8311083210432152308L;
-
- private String text = "";
- private BufferedImage image = null;
- private BufferedImage[] noImageImages = null;
- private int imageWidth, imageHeight;
- private int animationTime = 0;
-
- private AnimationThread animationThread = null;
-
- private class AnimationThread extends Thread {
-
- private boolean shutdown = false;
- private int counter = 0;
-
- public AnimationThread() {
- this.start();
- }
-
- public void shutdown() {
- this.shutdown = true;
- }
-
- @Override
- public void run() {
- while (!shutdown) {
- counter = (++counter % noImageImages.length);
- image = noImageImages[counter];
- repaint();
-
- try { Thread.sleep(animationTime); } catch (InterruptedException e) {}
- }
- }
-
- }
-
- public InfoPanel(String text, String[] noImageImageFileNames, int fps, int imageWidth, int imageHeight) {
- this.text = text;
- this.imageWidth = imageWidth;
- this.imageHeight = imageHeight;
- if (noImageImageFileNames == null || noImageImageFileNames.length == 0) {
- this.noImageImages = null;
- } else {
- this.noImageImages = new BufferedImage[noImageImageFileNames.length];
- for (int i = 0; i < noImageImageFileNames.length; ++i) {
- this.noImageImages[i] = loadImage(noImageImageFileNames[i]);
- }
- }
- this.animationTime = (fps == 0 ? 0 : 1000/fps);
- this.setImage(null);
- }
-
- protected static BufferedImage loadImage(String fileName) {
- BufferedImage image = null;
- try {
- InputStream in =
- FaceInfoPanel.class.getClassLoader().getResourceAsStream(fileName);
- if (in != null) {
- image = ImageIO.read(in);
- in.close();
- }
- } catch (IOException ex) {
- ex.printStackTrace();
-
- }
-
- return image;
- }
-
- @Override
- public void paint(Graphics g) {
- Graphics2D g2d = (Graphics2D) g;
-
- g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
- g2d.setRenderingHint(RenderingHints.KEY_INTERPOLATION,
- RenderingHints.VALUE_INTERPOLATION_NEAREST_NEIGHBOR);
-
- g2d.setBackground(new Color(0, 0, 0));
- g2d.clearRect(0, 0, this.getWidth(), this.getHeight());
-
- g2d.setColor(new Color(39, 53, 66));
- g2d.fillRoundRect(2, 2, this.getWidth()-4, this.getHeight()-4, 10, 10);
-
- g2d.setColor(new Color(118, 149, 174));
- g2d.drawString(text, 10, 20);
-
- g2d.setColor(new Color(81, 111, 137));
- g2d.drawRect(this.getWidth()-11-imageWidth, 9, imageWidth+1, imageHeight+1);
-
- if (image != null) {
- g2d.drawImage(image,
- this.getWidth() - 10 - imageWidth, 10,
- imageWidth, imageHeight, null);
- }
-
- g2d.setStroke(new BasicStroke(2.0f));
- g2d.setColor(new Color(81, 111, 137));
- g2d.drawRoundRect(2, 2, this.getWidth()-4, this.getHeight()-4, 10, 10);
- }
-
- protected synchronized void setImage(BufferedImage image) {
- if (image == null) {
- if (this.noImageImages != null && this.noImageImages.length > 0) {
- image = this.noImageImages[0];
- if (this.animationTime > 0) {
- if (this.animationThread == null)
- this.animationThread = new AnimationThread();
- }
- }
- } else {
- if (this.animationThread != null) {
- this.animationThread.shutdown();
- this.animationThread = null;
- }
- }
- this.image = image;
- this.repaint();
- }
-
-
-}
* along with LEA. If not, see <http://www.gnu.org/licenses/>.
*/
-
-
/**
* No description given.
*
*/
public class IntegralImageData {
- private long[][] integral;
- private Dimension dimension;
+ private long[][] integral;
+ private int width;
+ private int hegith;
- public IntegralImageData(BufferedImage bufferedImage) {
- this.integral = new long[bufferedImage.getWidth()][bufferedImage.getHeight()];
- this.dimension = new Dimension(bufferedImage.getWidth(), bufferedImage.getHeight());
+ // private Dimension dimension;
- int[] pixelBuffer = new int[bufferedImage.getWidth()*bufferedImage.getHeight()];
- PixelGrabber pg = new PixelGrabber(
- bufferedImage, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(), pixelBuffer, 0, bufferedImage.getWidth());
+ public IntegralImageData(Image bufferedImage) {
+ this.integral = new long[bufferedImage.getWidth()][bufferedImage.getHeight()];
+ this.width = bufferedImage.getWidth();
+ this.hegith = bufferedImage.getHeight();
+ // this.dimension = new Dimension(bufferedImage.getWidth(),
+ // bufferedImage.getHeight());
- try {
- pg.grabPixels();
- } catch (InterruptedException ie) {}
+ // int[] pixelBuffer = new int[bufferedImage.getWidth() *
+ // bufferedImage.getHeight()];
+ // PixelGrabber pg =
+ // new PixelGrabber(bufferedImage, 0, 0, bufferedImage.getWidth(),
+ // bufferedImage.getHeight(),
+ // pixelBuffer, 0, bufferedImage.getWidth());
+ //
+ // try {
+ // pg.grabPixels();
+ // } catch (InterruptedException ie) {
+ // }
- long[][] s = new long[bufferedImage.getWidth()][bufferedImage.getHeight()];
- for (int y = 0; y < bufferedImage.getHeight(); ++y) {
- for (int x = 0; x < bufferedImage.getWidth(); ++x) {
- s[x][y] = (y-1 < 0 ? 0 : s[x][y-1]) + (pixelBuffer[y*bufferedImage.getWidth() + x] & 0xff);
- this.integral[x][y] = (x-1 < 0 ? 0 : this.integral[x-1][y]) + s[x][y];
- }
- }
-
+ long[][] s = new long[bufferedImage.getWidth()][bufferedImage.getHeight()];
+ for (int y = 0; y < bufferedImage.getHeight(); ++y) {
+ for (int x = 0; x < bufferedImage.getWidth(); ++x) {
+ s[x][y] = (y - 1 < 0 ? 0 : s[x][y - 1]) + (bufferedImage.getPixel(x, y) & 0xff);
+ this.integral[x][y] = (x - 1 < 0 ? 0 : this.integral[x - 1][y]) + s[x][y];
+ }
}
- public long getIntegralAt(int x, int y) {
- return this.integral[x][y];
- }
+ }
- public Dimension getDimension() {
- return this.dimension;
- }
+ // public IntegralImageData(BufferedImage bufferedImage) {
+ // this.integral = new
+ // long[bufferedImage.getWidth()][bufferedImage.getHeight()];
+ // this.dimension = new Dimension(bufferedImage.getWidth(),
+ // bufferedImage.getHeight());
+ //
+ // int[] pixelBuffer = new
+ // int[bufferedImage.getWidth()*bufferedImage.getHeight()];
+ // PixelGrabber pg = new PixelGrabber(
+ // bufferedImage, 0, 0, bufferedImage.getWidth(), bufferedImage.getHeight(),
+ // pixelBuffer, 0, bufferedImage.getWidth());
+ //
+ // try {
+ // pg.grabPixels();
+ // } catch (InterruptedException ie) {}
+ //
+ // long[][] s = new long[bufferedImage.getWidth()][bufferedImage.getHeight()];
+ // for (int y = 0; y < bufferedImage.getHeight(); ++y) {
+ // for (int x = 0; x < bufferedImage.getWidth(); ++x) {
+ // s[x][y] = (y-1 < 0 ? 0 : s[x][y-1]) +
+ // (pixelBuffer[y*bufferedImage.getWidth() + x] & 0xff);
+ // this.integral[x][y] = (x-1 < 0 ? 0 : this.integral[x-1][y]) + s[x][y];
+ // }
+ // }
+ //
+ // }
- public int getWidth() {
- return this.dimension.width;
- }
+ public long getIntegralAt(int x, int y) {
+ return this.integral[x][y];
+ }
- public int getHeight() {
- return this.dimension.height;
- }
+ public int getWidth() {
+ return width;
+ }
+
+ public int getHeight() {
+ return hegith;
+ }
}
-import Benchmarks.oooJava.barneshut.FileInputStream;
-
/*
* Copyright 2009 (c) Florian Frankenberger (darkblue.de)
*
*/
public class LEA {
- private boolean showStatusWindow;
-
private boolean shutdown = false;
+ private LEAImplementation implementation;
- // private LEAImplementation implementation = new LEAImplementation();
+ private FaceAndEyePosition lastPositions = new FaceAndEyePosition(null, null);
+ private DeviationScanner deviationScanner = new DeviationScanner();
+ private int counter = 0;
// private ImageProcessor imageProcessor;
//
public LEA() {
// this.imageProcessor = new
// ImageProcessor(this.captureDevice.getFrameRate());
- // this.imageProcessor.start();
- LEAImplementation impl = new LEAImplementation();
- System.out.println("Done.");
+ implementation = new LEAImplementation();
}
/**
*/
public static void main(String[] args) throws Exception {
LEA lea = new LEA();
+ lea.doRun();
+ }
+
+ public void doRun() {
+
+ int maxCount = 1;
+ int i = 0;
+
+ ImageReader reader = new ImageReader();
+
+ while (i < maxCount) {
+ Image image = reader.readImage("data/e" + i + ".bmp");
+ i++;
+ if (image == null) {
+ break;
+ }
+ processImage(image);
+ }
+
+ System.out.println("Done.");
+
+ }
+
+ private void processImage(Image image) {
+
+ FaceAndEyePosition positions = implementation.getEyePosition(image);
+ if (positions.getEyePosition() != null) {
+ deviationScanner.addEyePosition(positions.getEyePosition());
+ Deviation deviation = deviationScanner.scanForDeviation(positions.getFacePosition());// positions.getEyePosition().getDeviation(lastPositions.getEyePosition());
+ // if (deviation != Deviation.NONE) {
+ // notifyEyeMovementListenerEyeMoved(deviation);
+ // }
+ }
+ // else {
+ // if (statusWindow != null)
+ // statusWindow.getEyeInfoPanel().setDeviation(null);
+ // }
+ lastPositions = positions;
+ // } catch (Exception e) {
+ // e.printStackTrace();
+ // try {
+ // close();
+ // } catch (Exception e2) {
+ // }
+ // }
}
}
*/
public class LEAImplementation {
- // private ClassifierTree classifierTree = null;
+ private ClassifierTree classifierTree;
- // private Rectangle2D lastRectangle;
+ private Rectangle2D lastRectangle;
public LEAImplementation() {
this.loadFaceData();
}
- // public FaceAndEyePosition getEyePosition(BufferedImage image) {
- // if (image == null)
- // return null;
- //
- // Rectangle2D faceRect = this.classifierTree.locateFaceRadial(image,
- // lastRectangle);
- // EyePosition eyePosition = null;
- // if (faceRect != null) {
- //
- // lastRectangle = faceRect;
- // Point point = readEyes(image, faceRect);
- // if (point != null) {
- // eyePosition = new EyePosition(point, faceRect);
- // }
- // }
- //
- // return new FaceAndEyePosition(faceRect, eyePosition);
- // }
+ public FaceAndEyePosition getEyePosition(Image image) {
+ if (image == null)
+ return null;
+
+ Rectangle2D faceRect = classifierTree.locateFaceRadial(image, lastRectangle);
+ System.out.println("FACE RECT=" + faceRect);
+ EyePosition eyePosition = null;
+ if (faceRect != null) {
+
+ lastRectangle = faceRect;
+ Point point = readEyes(image, faceRect);
+ if (point != null) {
+ eyePosition = new EyePosition(point, faceRect);
+ }
+ }
+
+ return new FaceAndEyePosition(faceRect, eyePosition);
+ }
+
+ private Point readEyes(Image image, Rectangle2D rect) {
+ EyeDetector ed = new EyeDetector(image, rect);
+ return ed.detectEye();
+ }
public boolean needsCalibration() {
return false;
FileInputStream inputFile = new FileInputStream("facedata.dat");
+ classifierTree = new ClassifierTree();
+
int numClassifier = Integer.parseInt(inputFile.readLine());
System.out.println("numClassifier=" + numClassifier);
for (int c = 0; c < numClassifier; c++) {
// 54,54,91,62,296.0
Point fromPoint = new Point();
Point toPoint = new Point();
- fromPoint.x = Integer.parseInt(inputFile.readLine());
+ fromPoint.x = Integer.parseInt(inputFile.readLine());
fromPoint.y = Integer.parseInt(inputFile.readLine());
toPoint.x = Integer.parseInt(inputFile.readLine());
toPoint.y = Integer.parseInt(inputFile.readLine());
classifier.setPossibilityFaceYes(Integer.parseInt(inputFile.readLine()));
classifier.setPossibilityFaceNo(Integer.parseInt(inputFile.readLine()));
+ classifierTree.addClassifier(classifier);
}
}
// private Point readEyes(BufferedImage image, Rectangle2D rect) {
+++ /dev/null
-/*
- * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
- *
- * This file is part of LEA.
- *
- * LEA is free software: you can redistribute it and/or modify it under the
- * terms of the GNU Lesser General Public License as published by the Free
- * Software Foundation, either version 3 of the License, or (at your option) any
- * later version.
- *
- * LEA is distributed in the hope that it will be useful, but WITHOUT ANY
- * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
- * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with LEA. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-/**
- *
- * @author Florian
- */
-class LEAStatusWindow extends javax.swing.JFrame {
-
- private static final long serialVersionUID = 6565861506173488477L;
-
- /** Creates new form LEAStatusWindow */
- public LEAStatusWindow() {
- initComponents();
- this.setLocationRelativeTo(null);
- }
-
- public FaceInfoPanel getFaceInfoPanel() {
- return (FaceInfoPanel)this.faceInfoPanel;
- }
-
- public EyeInfoPanel getEyeInfoPanel() {
- return (EyeInfoPanel)this.eyeInfoPanel;
- }
-
- /** This method is called from within the constructor to
- * initialize the form.
- * WARNING: Do NOT modify this code. The content of this method is
- * always regenerated by the Form Editor.
- */
- @SuppressWarnings("unchecked")
- // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
- private void initComponents() {
-
- jPanel1 = new javax.swing.JPanel();
- faceInfoPanel = new FaceInfoPanel();
- eyeInfoPanel = new EyeInfoPanel();
-
- setDefaultCloseOperation(javax.swing.WindowConstants.DO_NOTHING_ON_CLOSE);
- setTitle("LEA Status Window");
- setBackground(new java.awt.Color(0, 0, 0));
- setResizable(false);
-
- jPanel1.setBackground(new java.awt.Color(0, 0, 0));
-
- javax.swing.GroupLayout faceInfoPanelLayout = new javax.swing.GroupLayout(faceInfoPanel);
- faceInfoPanel.setLayout(faceInfoPanelLayout);
- faceInfoPanelLayout.setHorizontalGroup(
- faceInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 468, Short.MAX_VALUE)
- );
- faceInfoPanelLayout.setVerticalGroup(
- faceInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 119, Short.MAX_VALUE)
- );
-
- javax.swing.GroupLayout eyeInfoPanelLayout = new javax.swing.GroupLayout(eyeInfoPanel);
- eyeInfoPanel.setLayout(eyeInfoPanelLayout);
- eyeInfoPanelLayout.setHorizontalGroup(
- eyeInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 468, Short.MAX_VALUE)
- );
- eyeInfoPanelLayout.setVerticalGroup(
- eyeInfoPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGap(0, 60, Short.MAX_VALUE)
- );
-
- javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
- jPanel1.setLayout(jPanel1Layout);
- jPanel1Layout.setHorizontalGroup(
- jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
- .addContainerGap()
- .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING)
- .addComponent(eyeInfoPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- .addComponent(faceInfoPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- .addContainerGap())
- );
- jPanel1Layout.setVerticalGroup(
- jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addGroup(jPanel1Layout.createSequentialGroup()
- .addContainerGap()
- .addComponent(faceInfoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
- .addComponent(eyeInfoPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
- );
-
- javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
- getContentPane().setLayout(layout);
- layout.setHorizontalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
- );
- layout.setVerticalGroup(
- layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
- .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
- );
-
- pack();
- }// </editor-fold>//GEN-END:initComponents
-
-
- // Variables declaration - do not modify//GEN-BEGIN:variables
- private javax.swing.JPanel eyeInfoPanel;
- private javax.swing.JPanel faceInfoPanel;
- private javax.swing.JPanel jPanel1;
- // End of variables declaration//GEN-END:variables
-
-}
--- /dev/null
+public class Rectangle2D {
+
+ double x;
+ double y;
+ double width;
+ double height;
+
+ public Rectangle2D(double x, double y, double w, double h) {
+ this.x = x;
+ this.y = y;
+ this.width = w;
+ this.height = h;
+ }
+
+ public double getX() {
+ return x;
+ }
+
+ public double getY() {
+ return y;
+ }
+
+ public double getWidth() {
+ return width;
+ }
+
+ public double getHeight() {
+ return height;
+ }
+
+ public String toString() {
+ return "(" + x + "," + y + "," + width + "," + height + ")";
+ }
+}
PROGRAM=LEA
SOURCE_FILES=LEA.java
-BSFLAGS= -32bit -ssjava -mainclass $(PROGRAM) -heapsize-mb 1000 -nooptimize -debug -garbagestats -ssjavadebug #-printlinenum #-joptimize
+BSFLAGS= -32bit -ssjava -mainclass $(PROGRAM) -heapsize-mb 1000 -debug -garbagestats -ssjavadebug -printlinenum -joptimize #-nooptimize
default: $(PROGRAM)s.bin