Instance.java revision b6d99b7d17fd1bb1326a70744bd01be5d1586487
135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li/* 235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * Copyright (C) 2008-2009 The Android Open Source Project 335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * 435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * Licensed under the Apache License, Version 2.0 (the "License"); 535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * you may not use this file except in compliance with the License. 635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * You may obtain a copy of the License at 735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * 835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * http://www.apache.org/licenses/LICENSE-2.0 935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * 1035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * Unless required by applicable law or agreed to in writing, software 1135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * distributed under the License is distributed on an "AS IS" BASIS, 1235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * See the License for the specific language governing permissions and 1435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * limitations under the License. 1535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li */ 1635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 1735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Lipackage com.android.gesture; 1835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 19b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guyimport android.graphics.Matrix; 20b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guy 2135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li/** 2235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * An instance represents a sample if the label is available or a query if the 2335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * label is null. 2435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li */ 2535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Liclass Instance { 2635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private static final int SEQUENCE_SAMPLE_SIZE = 16; 2735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 28e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li private static final int PATCH_SAMPLE_SIZE = 16; 2935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 3035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private final static float[] ORIENTATIONS = { 3135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 0, 45, 90, 135, 180, -0, -45, -90, -135, -180 3235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li }; 3335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 3435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li // the feature vector 3535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li final float[] vector; 3635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 3735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li // the label can be null 3835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li final String label; 3935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 4035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li // the id of the instance 41c534727972c3835ed997e84a349f259915ef2cddRomain Guy final long id; 42e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li 4335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private Instance(long id, float[] sample, String sampleName) { 44c534727972c3835ed997e84a349f259915ef2cddRomain Guy this.id = id; 4535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li vector = sample; 4635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li label = sampleName; 47e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li } 48e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li 49e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li private void normalize() { 50e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li float[] sample = vector; 5135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float sum = 0; 52b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guy 5335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li int size = sample.length; 5435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li for (int i = 0; i < size; i++) { 5535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li sum += sample[i] * sample[i]; 5635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 57b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guy 58e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li float magnitude = (float) Math.sqrt(sum); 59e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li for (int i = 0; i < size; i++) { 60e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li sample[i] /= magnitude; 61e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li } 6235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 6335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 6435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li /** 6535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * create a learning instance for a single stroke gesture 6635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * 6735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * @param gesture 6835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * @param label 6935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * @return the instance 7035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li */ 71e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li static Instance createInstance(int samplingType, Gesture gesture, String label) { 7235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float[] pts; 73e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li Instance instance; 74e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li if (samplingType == GestureLibrary.SEQUENCE_SENSITIVE) { 75e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li pts = temporalSampler(samplingType, gesture); 76e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li instance = new Instance(gesture.getID(), pts, label); 77e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li instance.normalize(); 7835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } else { 7935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li pts = spatialSampler(gesture); 80e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li instance = new Instance(gesture.getID(), pts, label); 8135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 82e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li return instance; 8335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 84e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li 8535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private static float[] spatialSampler(Gesture gesture) { 86c534727972c3835ed997e84a349f259915ef2cddRomain Guy return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE); 8735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 8835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 89e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li private static float[] temporalSampler(int samplingType, Gesture gesture) { 90c534727972c3835ed997e84a349f259915ef2cddRomain Guy float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0), 9135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li SEQUENCE_SAMPLE_SIZE); 92c534727972c3835ed997e84a349f259915ef2cddRomain Guy float[] center = GestureUtilities.computeCentroid(pts); 9335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]); 9435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li orientation *= 180 / Math.PI; 9535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 9635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float adjustment = -orientation; 97e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li if (samplingType == GestureLibrary.ORIENTATION_SENSITIVE) { 9835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li int count = ORIENTATIONS.length; 9935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li for (int i = 0; i < count; i++) { 10035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float delta = ORIENTATIONS[i] - orientation; 10135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li if (Math.abs(delta) < Math.abs(adjustment)) { 10235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li adjustment = delta; 10335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 10435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 10535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 10635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 107b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guy Matrix m = new Matrix(); 10835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li m.setTranslate(-center[0], -center[1]); 109b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guy m.postRotate(adjustment); 11035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li m.mapPoints(pts); 111b6d99b7d17fd1bb1326a70744bd01be5d1586487Romain Guy 11235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li return pts; 11335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 11435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 11535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li} 116