1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27 package org.ximtec.igesture.algorithm.rubine;
28
29 import java.util.ArrayList;
30 import java.util.HashMap;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.concurrent.CountDownLatch;
34 import java.util.logging.Level;
35 import java.util.logging.Logger;
36
37 import org.apache.commons.math.linear.RealMatrix;
38 import org.apache.commons.math.linear.RealMatrixImpl;
39 import org.sigtec.ink.Note;
40 import org.ximtec.igesture.algorithm.feature.FeatureException;
41 import org.ximtec.igesture.core.Gesture;
42 import org.ximtec.igesture.core.GestureClass;
43 import org.ximtec.igesture.core.SampleDescriptor;
44 import org.ximtec.igesture.util.DoubleVector;
45 import org.ximtec.igesture.util.VectorTools;
46
47
48
49
50
51
52
53 public class GestureClassHelper implements Runnable {
54
55 private static final Logger LOGGER = Logger
56 .getLogger(GestureClassHelper.class.getName());
57
58 private GestureClass gestureClass;
59 private RubineConfiguration configuration;
60
61 private List<Gesture<Note>> samples;
62 private DoubleVector meanFeatureVector;
63
64
65
66
67 private Map<Gesture<Note>, GestureSampleHelper> sampleFeatureVector;
68
69 private RealMatrix realMatrix;
70
71 private double initialWeight;
72
73 private DoubleVector weightsVector;
74
75 private CountDownLatch latch;
76
77
78 public GestureClassHelper(GestureClass gestureClass,
79 RubineConfiguration configuration, CountDownLatch latch) {
80 this.gestureClass = gestureClass;
81 this.samples = getSamples();
82 this.configuration = configuration;
83 this.sampleFeatureVector = new HashMap<Gesture<Note>, GestureSampleHelper>();
84 this.latch = latch;
85 LOGGER.setLevel(Level.SEVERE);
86 }
87
88
89
90
91
92
93
94
95
96
97 private void computeFeatureVectors(GestureClass gestureClass)
98 throws FeatureException {
99
100
101 List<DoubleVector> vectors = new ArrayList<DoubleVector>();
102
103 for (Gesture<Note> sample : samples) {
104 try {
105
106
107
108
109
110
111
112
113
114
115 GestureSampleHelper helper = new GestureSampleHelper(sample
116 .getGesture(), configuration);
117 sampleFeatureVector.put(sample, helper);
118
119 if (VectorTools.hasValidValues(helper.getFeatureVector())) {
120 vectors.add(helper.getFeatureVector());
121 }
122 }
123 catch (FeatureException exception) {
124 LOGGER.warning("Could not compute the Feature Vector.");
125 }
126 }
127
128
129
130
131
132
133
134 if (vectors.size() > 0) {
135 meanFeatureVector = VectorTools.mean(vectors);
136 }
137 else {
138 throw new FeatureException(
139 "There are not enough samples for Gesture Class"
140 + gestureClass.getName());
141 }
142 }
143
144
145
146
147
148
149 private List<Gesture<Note>> getSamples() {
150 SampleDescriptor descriptor = gestureClass
151 .getDescriptor(SampleDescriptor.class);
152 return descriptor.getSamples();
153 }
154
155
156 @Override
157 public void run() {
158 try {
159 computeFeatureVectors(gestureClass);
160 }
161 catch (FeatureException exception) {
162 exception.printStackTrace();
163
164
165 }
166
167 getCovarianceMatrix();
168 latch.countDown();
169 }
170
171
172
173
174
175
176
177
178
179 public RealMatrix getCovarianceMatrix() {
180
181 if (realMatrix == null) {
182 int numOfFeatures = configuration.getNumberOfFeatures();
183 double[][] matrix = new double[numOfFeatures][numOfFeatures];
184
185 for (int i = 0; i < numOfFeatures; i++) {
186
187 for (int j = 0; j < numOfFeatures; j++) {
188 double sum = 0;
189
190 for (Gesture< ? > sample : samples) {
191 try {
192 sum += (sampleFeatureVector.get(sample).getFeatureVector()
193 .get(i) - meanFeatureVector.get(i))
194 * (sampleFeatureVector.get(sample).getFeatureVector()
195 .get(j) - meanFeatureVector.get(j));
196 }
197 catch (Exception e) {
198 e.printStackTrace();
199 }
200 }
201 matrix[i][j] = sum;
202 }
203 }
204
205 realMatrix = new RealMatrixImpl(matrix);
206 }
207
208 return realMatrix;
209 }
210
211
212 public DoubleVector getMeanFeatureVector() {
213 return meanFeatureVector;
214 }
215
216
217 public int getNumberOfSamples() {
218 return samples.size();
219 }
220
221
222 public void computeWeights(RealMatrix inverse) {
223 weightsVector = new DoubleVector(meanFeatureVector.size());
224
225 for (int j = 0; j < meanFeatureVector.size(); j++) {
226 double wci = 0;
227
228 for (int i = 0; i < meanFeatureVector.size(); i++) {
229 wci += inverse.getEntry(i, j) * meanFeatureVector.get(i);
230 }
231
232 weightsVector.set(j, wci);
233 }
234
235
236 double wc0 = 0;
237
238
239 for (int f = 0; f < meanFeatureVector.size(); f++) {
240 wc0 += weightsVector.get(f) * meanFeatureVector.get(f);
241 }
242
243 this.initialWeight = -0.5 * wc0;
244 }
245
246
247 public double getInitialWeight() {
248 return initialWeight;
249 }
250
251
252 public DoubleVector getWeights() {
253 return weightsVector;
254 }
255
256
257 public GestureClass getGestureClass() {
258 return gestureClass;
259 }
260
261 }