Instance.java revision e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886
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 1935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li/** 2035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * An instance represents a sample if the label is available or a query if the 2135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * label is null. 2235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li */ 2335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Liclass Instance { 2435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private static final int SEQUENCE_SAMPLE_SIZE = 16; 2535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 26e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li private static final int PATCH_SAMPLE_SIZE = 16; 2735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 2835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private final static float[] ORIENTATIONS = { 2935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 0, 45, 90, 135, 180, -0, -45, -90, -135, -180 3035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li }; 3135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 3235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li // the feature vector 3335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li final float[] vector; 3435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 3535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li // the label can be null 3635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li final String label; 3735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 3835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li // the id of the instance 39c534727972c3835ed997e84a349f259915ef2cddRomain Guy final long id; 40e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li 4135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private Instance(long id, float[] sample, String sampleName) { 42c534727972c3835ed997e84a349f259915ef2cddRomain Guy this.id = id; 4335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li vector = sample; 4435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li label = sampleName; 45e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li } 46e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li 47e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li private void normalize() { 48e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li float[] sample = vector; 4935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float sum = 0; 5035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li int size = sample.length; 5135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li for (int i = 0; i < size; i++) { 5235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li sum += sample[i] * sample[i]; 5335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 54e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li float magnitude = (float) Math.sqrt(sum); 55e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li for (int i = 0; i < size; i++) { 56e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li sample[i] /= magnitude; 57e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li } 5835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 5935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 6035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li /** 6135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * create a learning instance for a single stroke gesture 6235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * 6335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * @param gesture 6435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * @param label 6535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li * @return the instance 6635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li */ 67e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li static Instance createInstance(int samplingType, Gesture gesture, String label) { 6835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float[] pts; 69e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li Instance instance; 70e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li if (samplingType == GestureLibrary.SEQUENCE_SENSITIVE) { 71e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li pts = temporalSampler(samplingType, gesture); 72e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li instance = new Instance(gesture.getID(), pts, label); 73e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li instance.normalize(); 7435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } else { 7535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li pts = spatialSampler(gesture); 76e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li instance = new Instance(gesture.getID(), pts, label); 7735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 78e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li return instance; 7935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 80e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li 8135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li private static float[] spatialSampler(Gesture gesture) { 82c534727972c3835ed997e84a349f259915ef2cddRomain Guy return GestureUtilities.spatialSampling(gesture, PATCH_SAMPLE_SIZE); 8335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 8435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 85e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li private static float[] temporalSampler(int samplingType, Gesture gesture) { 86c534727972c3835ed997e84a349f259915ef2cddRomain Guy float[] pts = GestureUtilities.temporalSampling(gesture.getStrokes().get(0), 8735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li SEQUENCE_SAMPLE_SIZE); 88c534727972c3835ed997e84a349f259915ef2cddRomain Guy float[] center = GestureUtilities.computeCentroid(pts); 8935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float orientation = (float) Math.atan2(pts[1] - center[1], pts[0] - center[0]); 9035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li orientation *= 180 / Math.PI; 9135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 9235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float adjustment = -orientation; 93e6ea003ab66ea8bd91bed8aaf5c3b4cd75555886Yang Li if (samplingType == GestureLibrary.ORIENTATION_SENSITIVE) { 9435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li int count = ORIENTATIONS.length; 9535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li for (int i = 0; i < count; i++) { 9635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li float delta = ORIENTATIONS[i] - orientation; 9735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li if (Math.abs(delta) < Math.abs(adjustment)) { 9835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li adjustment = delta; 9935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 10035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 10135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 10235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 10335aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li android.graphics.Matrix m = new android.graphics.Matrix(); 10435aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li m.setTranslate(-center[0], -center[1]); 10535aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li android.graphics.Matrix rotation = new android.graphics.Matrix(); 10635aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li rotation.setRotate(adjustment); 10735aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li m.postConcat(rotation); 10835aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li m.mapPoints(pts); 10935aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li return pts; 11035aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li } 11135aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li 11235aa84b1f9f5e42dd00cb66df993ed1628c8963bYang Li} 113