EyeTracking has the same result of the original Java version.
[IRC.git] / Robust / src / Benchmarks / SSJava / EyeTracking / LEA.java
1 /*
2  * Copyright 2009 (c) Florian Frankenberger (darkblue.de)
3  * 
4  * This file is part of LEA.
5  * 
6  * LEA is free software: you can redistribute it and/or modify it under the
7  * terms of the GNU Lesser General Public License as published by the Free
8  * Software Foundation, either version 3 of the License, or (at your option) any
9  * later version.
10  * 
11  * LEA is distributed in the hope that it will be useful, but WITHOUT ANY
12  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
13  * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
14  * details.
15  * 
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with LEA. If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 /**
21  * This is the main class of LEA.
22  * <p>
23  * It uses a face detection algorithm to find an a face within the provided
24  * image(s). Then it searches for the eye in a region where it most likely
25  * located and traces its position relative to the face and to the last known
26  * position. The movements are estimated by comparing more than one movement. If
27  * a movement is distinctly pointing to a direction it is recognized and all
28  * listeners get notified.
29  * <p>
30  * The notification is designed as observer pattern. You simply call
31  * <code>addEyeMovementListener(IEyeMovementListener)</code> to add an
32  * implementation of <code>IEyeMovementListener</code> to LEA. When a face is
33  * recognized/lost or whenever an eye movement is detected LEA will call the
34  * appropriate methods of the listener
35  * <p>
36  * LEA also needs an image source implementing the <code>ICaptureDevice</code>.
37  * One image source proxy to the <code>Java Media Framework</code> is included (
38  * <code>JMFCaptureDevice</code>).
39  * <p>
40  * Example (for using LEA with <code>Java Media Framework</code>):
41  * <p>
42  * <code>
43  * LEA lea = new LEA(new JMFCaptureDevice(), true);
44  * </code>
45  * <p>
46  * This will start LEA with the first available JMF datasource with an extra
47  * status window showing if face/eye has been detected successfully. Please note
48  * that face detection needs about 2 seconds to find a face. After detection the
49  * following face detection is much faster.
50  * 
51  * @author Florian Frankenberger
52  */
53 public class LEA {
54
55   private boolean shutdown = false;
56   private LEAImplementation implementation;
57
58   private FaceAndEyePosition lastPositions = new FaceAndEyePosition(null, null);
59   private DeviationScanner deviationScanner = new DeviationScanner();
60   private int counter = 0;
61
62   // private ImageProcessor imageProcessor;
63   //
64   // private class ImageProcessor extends TimedThread {
65   //
66   // private FaceAndEyePosition lastPositions = new FaceAndEyePosition(null,
67   // null);
68   // private DeviationScanner deviationScanner = new DeviationScanner();
69   // private int counter = 0;
70   //
71   // private int fps;
72   //
73   // public ImageProcessor(int fps) {
74   // super(fps);
75   // this.fps = fps;
76   // }
77   //
78   // @Override
79   // public void doRun() {
80   //
81   // BufferedImage image = captureDevice.getImage();
82   // if (image == null)
83   // return;
84   //
85   // try {
86   // FaceAndEyePosition positions = implementation.getEyePosition(image);
87   //
88   // if (((lastPositions.getFacePosition() == null &&
89   // positions.getFacePosition() != null) || (lastPositions
90   // .getFacePosition() != null && positions.getFacePosition() == null)) ||
91   // counter++ > fps) {
92   //
93   // if ((lastPositions.getFacePosition() == null && positions.getFacePosition()
94   // != null)
95   // || (lastPositions.getFacePosition() != null && positions.getFacePosition()
96   // == null)) {
97   // if (positions.getFacePosition() != null) {
98   // notifyEyeMovementListenerFaceDetected();
99   // } else {
100   // notifyEyeMovementListenerFaceLost();
101   // }
102   // }
103   // counter = 0;
104   // if (statusWindow != null)
105   // statusWindow.getFaceInfoPanel().setFace(image,
106   // positions.getFacePosition());
107   // }
108   //
109   // if (positions.getEyePosition() != null) {
110   // if (statusWindow != null) {
111   // statusWindow.getEyeInfoPanel().setEyePosition(image,
112   // positions.getFacePosition(),
113   // positions.getEyePosition());
114   // }
115   // deviationScanner.addEyePosition(positions.getEyePosition());
116   // Deviation deviation =
117   // deviationScanner.scanForDeviation(positions.getFacePosition());//
118   // positions.getEyePosition().getDeviation(lastPositions.getEyePosition());
119   //
120   // if (deviation != Deviation.NONE) {
121   // notifyEyeMovementListenerEyeMoved(deviation);
122   // }
123   //
124   // } else {
125   // if (statusWindow != null)
126   // statusWindow.getEyeInfoPanel().setDeviation(null);
127   // }
128   //
129   // lastPositions = positions;
130   // } catch (Exception e) {
131   // e.printStackTrace();
132   // try {
133   // close();
134   // } catch (Exception e2) {
135   // }
136   // }
137   // }
138   //
139   // public synchronized void clearDeviationScanner() {
140   // this.deviationScanner.clear();
141   // }
142   //
143   // }
144
145   public LEA() {
146     // this.imageProcessor = new
147     // ImageProcessor(this.captureDevice.getFrameRate());
148     implementation = new LEAImplementation();
149   }
150
151   /**
152    * Clears the internal movement buffer. If you just capture some of the eye
153    * movements you should call this every time you start recording the
154    * movements. Otherwise you may get notified for movements that took place
155    * BEFORE you started recording.
156    */
157   public void clear() {
158     // this.imageProcessor.clearDeviationScanner();
159   }
160
161   /**
162    * To test LEA with the first capture device from the
163    * <code>Java Media Framework</code> just start from here.
164    * 
165    * @param args
166    * @throws Exception
167    */
168   public static void main(String[] args) throws Exception {
169     LEA lea = new LEA();
170     lea.doRun();
171   }
172
173   public void doRun() {
174
175     int maxCount = 37;
176     int i = 0;
177
178     ImageReader reader = new ImageReader();
179
180     while (i < maxCount) {
181       Image image = reader.readImage("data/b" + i + ".bmp");
182       i++;
183       if (image == null) {
184         break;
185       }
186       processImage(image);
187     }
188
189     System.out.println("Done.");
190
191   }
192
193   private void processImage(Image image) {
194
195     FaceAndEyePosition positions = implementation.getEyePosition(image);
196
197     if (positions.getEyePosition() != null) {
198       deviationScanner.addEyePosition(positions.getEyePosition());
199       Deviation deviation = deviationScanner.scanForDeviation(positions.getFacePosition());// positions.getEyePosition().getDeviation(lastPositions.getEyePosition());
200       if (deviation != DeviationScanner.NONE) {
201         System.out.println("deviation=" + deviation);
202         // notifyEyeMovementListenerEyeMoved(deviation);
203       }
204     }
205     // else {
206     // if (statusWindow != null)
207     // statusWindow.getEyeInfoPanel().setDeviation(null);
208     // }
209     lastPositions = positions;
210     // } catch (Exception e) {
211     // e.printStackTrace();
212     // try {
213     // close();
214     // } catch (Exception e2) {
215     // }
216     // }
217   }
218
219 }