• android学习笔记47android_手势识别技术的实现,手势库的创建


    2013年5月9日
    47_手势识别
    --------------------
    第一步:建立手势库
    使用SDK自带例子GestureBuilder建立手势库(位置:android-sdk-windows\samples\android-8\GestureBuilder)。使用GestureBuilder之前,你需要恢复其到开发环境,然后进行编绎并部署到手机上。此时,就可以使用GestureBuilder建立手势库,生成的手势库文件在SCDard上,默认文件名称为:gestures

    第二步:在应用中加载手势库文件,然后开发手势识别代码。
    把手势库文件gestures文件拷贝到项目的res/raw目录下。然后在布局文件中添加用于手势绘制的View:
     <android.gesture.GestureOverlayView
        android:id="@+id/gestures"
        android:layout_width="fill_parent“ android:layout_height="0dip"
        android:layout_weight="1.0"
        />
    大多数情况下,手势都是通过一笔完成。然而有一些特别的需求就需要通过多个笔画来实现,这时可以使用gestureStrokeType属性进行设置:Multiple:1

    手势识别代码见ppt下方
    public class MainActivity extends Activity {
        private GestureOverlayView gestureOverlayView;
        private GestureLibrary mLibrary;
        private boolean state;
        private EditText addressText;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            addressText = (EditText)this.findViewById(R.id.address);
            gestureOverlayView = (GestureOverlayView)this.findViewById(R.id.gestures);
            //当用户完成一次Gesture绘制后,系统将自动调用Listener对象的onGesturePerformed()方法
            gestureOverlayView.addOnGesturePerformedListener(new GestureListener());
            mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
            state = mLibrary.load();//加载手势库
        }
       
        private final class GestureListener implements GestureOverlayView.OnGesturePerformedListener{
      @Override
      public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
       if(state){
        List<Prediction> predictions = mLibrary.recognize(gesture);//从手势库中查询匹配的内容,匹配的结果可能包括多个相似的结果,匹配度高的结果放在最前面
        if(!predictions.isEmpty()){
         Prediction prediction = predictions.get(0);
         //prediction的score属性代表了与手势的相似程度
         //prediction的name代表手势对应的字母
         if(prediction.score > 1){
          addressText.setText(prediction.name);
         }
        }
       }
      }
        }
    }
    ---------------------------------------
    2.相关理解:手势识别其实就是图形识别,当用户画出图形后,由程序识别然后按照识别的结果进行执行。
    ----------------------------------------------------------------------------------------------------
    3.导入一个android项目到eclipse工作workspace中的方法:
      a.在已经workspace已经存在的android项目中拷贝.classpath,.project,project.properties(这里应该是default.properties文件)到
        需要导入的项目中
      b.然后直接导入项目到eclipse中就可以了
      ---------------------------------------------------------
    4.a、这里要实现的功能是,当用户画出一个对勾后,关闭该应用。
      b、当用户画一个L后,就给李德伟打电话
      ------------------------------------------------------
    5.首先要建立手势库,手势识别的时候会从手势库中查找,如果找到就执行相应的业务功能
    ----------------------------------------------------------------
    6.WARNING: Application does not specify an API level requirement!
    [2009-12-27 16:51:33 - Tank] WARNING: Application does not specify an API level requirement!
    [2009-12-27 16:51:33 - Tank] Device API version is 3 (Android 1.5)
    网上一查是由于没有指定users sdk的缘故,修改AndroidManifest.xml文件.
    加入:
    <uses-sdk android:minSdkVersion="3"></uses-sdk>
    加在<manifest> </manifest> 之间.
    ------------------------------------------------------
    7.2013/5/10
    ----------------
    8.[2013-05-10 22:54:48 - GestureBuilder] Re-installation failed due to different application signatures.
    [2013-05-10 22:54:48 - GestureBuilder] You must perform a full uninstall of the application. WARNING: This will remove the application data!
    [2013-05-10 22:54:48 - GestureBuilder] Please execute 'adb uninstall com.android.gesture.builder' in a shell.
    [2013-05-10 22:54:48 - GestureBuilder] Launch canceled!
    这时先运行android模拟机,进入命令行,当然你要定位adb.exe的目录,我是放在E:\android\android-sdk-windows\platform-tools 下
     E:\android\android-sdk-windows\platform-tools> adb uninstall com.android.gesture.builder.
     重新运行就可以了
     --------------------------------------------------
    9.这里建立手势库的时候,用的是android自带的一个例子:
      这个例子可以在这里找到:
      G:\李鹏视频\andoid程序学习及开发\3G手机Android应用开发\3G手机Android应用开发开发资料\开发资料\android-sdk_r06-windows\android-sdk-windows\samples\android-8
      就是这个项目:GestureBuilder
      ---------------------------------------
    10.如果出现问题按照上面的方法进行解决
       运行该例子程序后:点击Add gesture进行手势添加,也就是添加用户自己画的图片
       添加的时候,只要在空白区域画出手势,在Name中输入手势名称就,然后点击Done就
       可以添加一个手势了
    -------------------------------
    11.当添加完手势后,可以查看在sdcard根目录下,有gestures这个文件,这个就是手势库文件
       也是一个数据库文件,这时候就可以在这个手势库的基础上进行手势的查找识别了。
       ---------------------------------------------------------------------------------------
       11-1:做的时候首先将上一步生成的手势库文件gestures复制到:/gesture/res/raw/gestures这个路径下,当查不到的时候需要关闭应用
       11-2:关闭应用的方法:
              当应用不再使用时,通常需要关闭应用,可以使用以下两种方法关闭android应用:

    第一种方法:首先获取当前进程的id,然后杀死该进程。 (建议使用)
    android.os.Process.killProcess(android.os.Process.myPid())

    第二种方法:终止当前正在运行的Java虚拟机,导致程序终止
    System.exit(0);

    第三种方法:强制关闭与该包有关联的一切执行
    ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);   
    manager.restartPackage(getPackageName());
    <uses-permission android:name="android.permission.RESTART_PACKAGES" />
    ----------------------------------------------------------------------------------------
    12.下面是手势识别实例的所有源码:
       屏幕布局:
       --------------
       整个屏幕都是供用户绘制手势
       在屏幕右下角有个识别按钮
    ---------------------------------
      a.新建android项目:gesture
      b./gesture/src/com/credream/gesture/GestureActivity.java
        package com.credream.gesture;

    import java.util.ArrayList;

    import android.app.Activity;
    import android.content.Intent;
    import android.gesture.Gesture;
    import android.gesture.GestureLibraries;
    import android.gesture.GestureLibrary;
    import android.gesture.GestureOverlayView;
    import android.gesture.GestureOverlayView.OnGestureListener;
    import android.gesture.GestureOverlayView.OnGesturePerformedListener;
    import android.gesture.Prediction;
    import android.net.Uri;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.MotionEvent;
    import android.view.View;
    import android.widget.Toast;

    public class GestureActivity extends Activity {
     private static final String TAG = "GestureActivity";
        private  GestureLibrary library;
     private Gesture mgesture;
        private GestureOverlayView overlayView;
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.main);
            //fromRawResource从raw这个手势库文件中得到手势对象
            library = GestureLibraries.fromRawResource(this, R.raw.gestures);
            //加载手势对象
            library.load();
            //获取overlayView,也就是用户识别手势的画板。
            overlayView = (GestureOverlayView) this.findViewById(R.id.gestures);
            //只针对单笔手势:overlayView.addOnGesturePerformedListener(new GesturePerformedListener());
            //当用户绘制完手势之后,就会触发一个事件
            //overlayView.addOnGesturePerformedListener(new GesturePerformedListener());
            //注意这里GesturePerformedListener这个方法只是针对单笔手势的,用户画多笔的时候会没有响应
            overlayView.addOnGestureListener(new GestureListener());
            //addOnGestureListener,这个方法,既可以实现单笔手势,也可以实现多笔手势
        }
        // ②.在这个方法中识别手势
        public void find(View v){
         recognize(mgesture);
         //②.1 识别完之后,清除。
         overlayView.clear(true);
        }
        //②.下面这个方法可以识别单笔,也可以识别多笔。
        private final class GestureListener implements OnGestureListener{
     
         public void onGestureStarted(GestureOverlayView overlay, MotionEvent event) {
       Log.i(TAG, "onGestureStarted()");
       //可以打印到控制台,得到这三个方法的调用顺序。
       //-----------------------------------------
       /*这三个方法的调用顺序是,当用户画第一笔的时候,调用onGestureStarted方法
        * 当用户在画第一笔的过程中不断调用onGesture这个方法
        * 当用户画完第一笔的时候调用onGestureEnded这个方法
        * 当用户开始画第二笔的时候调用onGestureStarted这个方法,一次循环。。
        * */
       //-------------------------------------------
      }
      public void onGesture(GestureOverlayView overlay, MotionEvent event) {
       Log.i(TAG, "onGesture()");
      }
      public void onGestureEnded(GestureOverlayView overlay, MotionEvent event) {
       Log.i(TAG, "onGestureEnded()");
       //因为这个方法是最后调用的,所以在这个方法里得到用户最后画完的手势
       mgesture = overlay.getGesture();
       //取得用户最后画完的手势
      }
      public void onGestureCancelled(GestureOverlayView overlay, MotionEvent event) {
       Log.i(TAG, "onGestureCancelled()");
      }
        }
        //①.以下方法只识别单笔绘图。
      //当用户绘制完手势之后,就会触发一个事件,就会调用这个方法,把用户绘制完的手势传进来
        private final class GesturePerformedListener implements OnGesturePerformedListener{
      //overlay这个参数其实就是取得用户绘制所用的那个画板,这里是overlayView
         public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
       //在这个方法中就来识别用户画出的手势,也就是把用户绘制的手势在手势库中查找,查找到就是
          //代表可以识别。
          //这时候把导出的手势库文件gesture,添加到
          ///gesture/res/raw这个路径中,注意这里raw是新建的文件夹
          //然后查看R文件就可以看到下面这些:
          //public static final int gestures=0x7f040000;
          //识别手势, recognize(gesture)这个方法会在手势库中查找,如果找到匹配项
          //会以集合的形式返回
          
         //ArrayList<Prediction> predictions=library.recognize(gesture);
         //这个集合中的元素排序原则是最匹配的在最上边,其次是不怎么匹配的。
         //这个方法会把所有匹配的记录查询出来,并且把最匹配的在最上边
           recognize(gesture);
      }  
        }
       
        private void recognize(Gesture gesture) {
         //这个集合中的元素排序原则是最匹配的在最上边,其次是不怎么匹配的。
         //这个方法会把所有匹配的记录查询出来,并且把最匹配的在最上边
         ArrayList<Prediction> predictions = library.recognize(gesture);
      if(!predictions.isEmpty()){//当结果集合不是空的时候,就说明有匹配
       //得到最匹配的那个,也就是第一条记录
       Prediction prediction = predictions.get(0);
       //prediction.score>0-10这个是匹配值,范围:prediction.score>0-10
       //这个值为10的时候,代表手势库中的图和用户绘制的图有10%的匹配度
       if(prediction.score >= 6){
        //这里要求匹配度要在60%以上
        //如果名称为李德伟lidewei
        if("lidewei".equals(prediction.name)){
         //调用打电话意图,
         Intent intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:1350505050"));
         //通过意图调用打电话的activity,这里需要有拨号权限
         startActivity(intent);
        }else if("close".equals(prediction.name)){
         finish();//关闭Activity,也就是关闭窗口
        //当activity关闭的时候,其实应用还存在,这里需要关闭应用
         //当activity关闭的时候,会调用onDestroy方法,在这个方法里
         //可以直接杀掉进程
        }
       }else{
        //匹配度不够6的时候,提示匹配度太低
        Toast.makeText(getApplicationContext(), R.string.low, 1).show();
       }
      }else{
       //没有匹配的记录
       Toast.makeText(getApplicationContext(), R.string.notfind, 1).show();
      }
     }
     @Override
     protected void onDestroy() {
      super.onDestroy();
      //这里直接杀掉进程:首先取得当前进程的id,然后调用killProcess杀掉进程
              android.os.Process.killProcess(android.os.Process.myPid());//关闭应用
     }
    }
    -----------------------------------------------------------
    c./gesture/res/values/strings.xml
      <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="hello">Hello World, MainActivity!</string>
        <string name="app_name">手势识别</string>
        <string name="notfind">不匹配</string>
        <string name="low">匹配度太低</string>
        <string name="recognize">识别</string>
    </resources>
    --------------------------------------------------
    d./gesture/AndroidManifest.xml
      <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="com.credream.gesture"
        android:versionCode="1"
        android:versionName="1.0" >

        <uses-sdk android:minSdkVersion="8" />

        <application
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name" >
            <activity
                android:label="@string/app_name"
                android:name=".GestureActivity" >
                <intent-filter >
                    <action android:name="android.intent.action.MAIN" />

                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
        </application>
    <!-- 由于识别成功后会给李德伟拨打电话,所以这里需要这个权限 -->
    <uses-permission android:name="android.permission.CALL_PHONE"/>
           
    </manifest>
    -----------------------------------------------------
    e./gesture/res/layout/main.xml
      <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        >
        <!-- 这个控件可以供用户在他上面绘制手势 -->
     <android.gesture.GestureOverlayView
         android:id="@+id/gestures"
         android:layout_width="fill_parent"
         android:layout_height="0dp"
         android:layout_weight="1"
         android:gestureStrokeType="multiple"
         />
     <!-- ①.1 android:layout_height="0dp",设置用户绘制手势界面的高度
     ①.2 android:layout_weight="1",设置定义测量的优先级别,0的优先级最高,0>1>2...
           按钮的话,android:layout_weight="1"这个默认值是0
     ①.3 系统首先测量按钮的高度,因为按钮的优先级高。
     ④.4 只要这样设置就可以实现用窗口的高度,减去按钮的高度,剩余的,就是用户绘制手势的高度
      -->
     <!-- android:gestureStrokeType="multiple"注意加上这一句就可以进行多笔画识别
     以前只可以写一笔,现在可以写好几笔画。
      -->
    <!-- ①. android:layout_weight="0"这里要求让这个按钮显示在屏幕的最下方
      这里采取的方法是,用窗口的高度,减去按钮的高度,剩余的,就是用户绘制手势的高度 -->
     <Button
     android:layout_weight="0"
      android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/recognize"
        android:onClick="find"
        />
    </LinearLayout>
    ------------------------------------------------------------------------------------
    13.这个功能可以做成,用户输入密码。
       手势识别,可以用于软件的快捷方式。比如用户想打开某个应用画个o就可以。
       使用手势识别可以实现解锁功能。
    ----------------------------------------------------------------------------

  • 相关阅读:
    值类型和引用类型区别
    json数据类型
    转:不再以讹传讹,GET和POST的真正区别
    简单投票系统学到的一些东西
    jq 全选和反选以及判断那条被选中
    PHP中获取当前页面的完整URL
    jq div鼠标放上、离开马上展开、收缩方法
    js 删除确定
    mysql 存储过程
    js 闭包原理理解
  • 原文地址:https://www.cnblogs.com/javawebsoa/p/3073190.html
Copyright © 2020-2023  润新知