OpenCVforAndroid应用之银行卡号识别 ------ 搞定开发环境

南七忆梦 2016-01-22

前阵子的考试、旅游让我有很长一阵子没来博客看看,现在寒假了,是时候写点、看点新的东西了!

前面我主要围绕着基于OpenCV的机器学习算法在图像识别处理上的应用来展开学习的,当然这些个技术(如银行卡号识别)最终都是要运用到实际生活中的。我们就拿银行卡号识别来说,大家用的最多的微信实际上就有了这个功能。大家打开微信钱包,绑定银行卡的时候是否在输入框右侧看到一个照相机一样的按钮呢,那就是实现银行卡号识别功能的地方。现在我们也模仿微信,将opencv机器学习移植到android上。

这个app是我之前用很短的时间完成的,旨在:

1.进一步了解android编程

2.了解opencv移植到android的过程,方便开发

3.了解C++移植到android的过程,方便开发

我要完成的这个简单的app主要功能是:

1.通过手机相册中已有的照片(银行卡片)识别银行卡号(暂定农行)

2.通过手机拍照得到银行卡图片识别银行卡号(暂定农行)

由于开发时间较短,实现比较简单,主要是想尽快将成果整合出来,我将用两三篇博客总结一下主要技术要点,接下来是第一部分:

                                                             

                                            一、搞定开发环境

             (1) OpenCVforAndroid

               环境搭建

               1> eclipse for android(推荐直接下载adt-bundle-windows)

                    Java作为现在android编程最主流的语言,eclipse是必不可少的编程环境,现在网上有很多自带adt插件的eclipse,当然你也可以下载adt插件,在eclipse下配置,这里推荐前者,省心省事方便无穷。

                   2>导入OpenCV Library

                   在OpenCV官网下载最新的OpenCVforAndroid,解压到workspace所在盘下;
                                                    OpenCVforAndroid应用之银行卡号识别 ------  搞定开发环境 

                   进入eclipse,导入OpenCV Library(在项目一栏中右击选择Import);
                                                         OpenCVforAndroid应用之银行卡号识别 ------  搞定开发环境选择上图所选选项

                  选择……\OpenCV-android-sdk\sdk,就可将OpenCV导入到Eclipse中。
                                                       OpenCVforAndroid应用之银行卡号识别 ------  搞定开发环境

                                                      OpenCVforAndroid应用之银行卡号识别 ------  搞定开发环境导入成功!


                     测试程序

                 1>新建一个android application project

                      2> 导入OpenCV Library,右键项目,点击“Bulid Path”,选择configure build path,add我们导入的OpenCV Library。

                      3> 编程验证:点击按钮,灰度化图片            

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
	    xmlns:tools="http://schemas.android.com/tools"
	    android:layout_width="match_parent"
	    android:layout_height="match_parent"
	    android:paddingBottom="@dimen/activity_vertical_margin"
	    android:paddingLeft="@dimen/activity_horizontal_margin"
	    android:paddingRight="@dimen/activity_horizontal_margin"
	    android:paddingTop="@dimen/activity_vertical_margin"
	    tools:context="com.example.useopencvtest.MainActivity" >
	
	    <TextView
	        android:id="@+id/textView1"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:text="@string/hello_world" />
	
	    <ImageView
	        android:id="@+id/imageView2"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_alignLeft="@+id/imageView1"
	        android:layout_alignParentBottom="true"
	        android:layout_marginBottom="159dp"
	        android:src="@drawable/abc_ab_solid_light_holo" />
	
	    <ImageView
	        android:id="@+id/imageView1"
	        android:layout_width="100dp"
	        android:layout_height="150dp"
	        android:layout_below="@+id/textView1"
	        android:layout_centerHorizontal="true"
	        android:layout_marginTop="27dp"
	        android:src="@drawable/bank" />
	
	    <Button
	        android:id="@+id/button1"
	        android:layout_width="wrap_content"
	        android:layout_height="wrap_content"
	        android:layout_alignTop="@+id/imageView2"
	        android:layout_marginTop="43dp"
	        android:layout_toRightOf="@+id/imageView1"
	        android:text="Button" />
	
	</RelativeLayout>
package com.example.useopencvtest;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import android.content.pm.ApplicationInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;

import com.example.useopencvtest.R.id;


public class MainActivity extends ActionBarActivity {
	ImageView image;
	Button btn;
	String TAG = "AAA";
	 //OpenCV库加载并初始化成功后的回调函数   
    private  BaseLoaderCallback mLoaderCallback =  new  BaseLoaderCallback( this ) {  
 
        @Override   
        public   void  onManagerConnected( int  status) {  
            // TODO Auto-generated method stub   
            switch  (status){  
            case  BaseLoaderCallback.SUCCESS:  
               Log.i(TAG,  "成功加载" );  
                break ;  
            default :  
                super .onManagerConnected(status);  
               Log.i(TAG,  "加载失败" );  
                break ;  
           }  
       }  
   };  
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        image = (ImageView)findViewById(R.id.imageView2);
        btn = (Button)findViewById(id.button1);
        btn.setOnClickListener( new  ProcessClickListener());  
    }
    
    private   class  ProcessClickListener  implements  OnClickListener{  
        
        @Override   
        public   void  onClick(View v) {  
            // TODO Auto-generated method stub   
        	use();
       	}  
   }  

    public void use()
    {
        Bitmap bitmap = getRes("bank");
        Mat temp = new Mat();
        Mat mat = new Mat();
    	Utils.bitmapToMat(bitmap, temp);
    	Imgproc.cvtColor(temp, mat, Imgproc.COLOR_BGR2GRAY);
    	Utils.matToBitmap(mat, bitmap);
    	this.image.setImageBitmap(bitmap); 
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
    
    public Bitmap getRes(String name) {//获得res文件夹下的图片,得到bmp图片
   	 ApplicationInfo appInfo = getApplicationInfo();
   	 int resID = getResources().getIdentifier(name, "drawable", appInfo.packageName);
   	 return BitmapFactory.decodeResource(getResources(), resID);
   	 }
    
    @Override   
    protected   void  onResume() {  
        // TODO Auto-generated method stub   
        super .onResume();  
        //load OpenCV engine and init OpenCV library   
       OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_4, getApplicationContext(), mLoaderCallback);  
       Log.i(TAG,  "onResume sucess load OpenCV..." );  
//     new Handler().postDelayed(new Runnable(){   
//  
//         @Override   
//         public void run() {   
//             // TODO Auto-generated method stub   
//             procSrc2Gray();   
//         }   
//            
//     }, 1000);   
         
   }  
}

 结果:
                                                               OpenCVforAndroid应用之银行卡号识别 ------  搞定开发环境
         参考:http://blog.csdn.net/yanzi1225627/article/details/16917961

              (2)Java的C++接口--------JNI

             环境搭建

             很多情况是开发者已经用C++进行了opencv的开发,想在移动端直接使用,这时候使用opencvforandroid就显得麻烦很多了,那这里我们可以使用Java中的JNI接口,直接调用C++的代码。

                 需要的工具:在(1)中的基础上,只需要安装NDK就可以了(r8版本以上)(注:现在你在百度上搜索的大部分还是写的NDK+Cygwin,但是实际上新版本的NDK(r8以上,我用的是r10版本)是不需要下载Cygwin,下过的朋友知道,这个玩意很坑的,我当初下了一个晚上都没下好)

                在下载安装好NDK后,参照             http://jingyan.baidu.com/article/5d6edee22d908799eadeec9f.html配置NDK。

               编程测试:

               MainActivity.java

              

package com.example.haveimgfun;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Bitmap.Config;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;


public class MainActivity extends ActionBarActivity {
	
	ImageView imgHuaishi;  
	Button btnNDK;
    
	@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        imgHuaishi = (ImageView)findViewById(R.id.img_huaishi);
        btnNDK = (Button)findViewById(R.id.btn_gray_process);
      //  btnNDK.setOnClickListener( new  MyClickListener());  
        btnNDK.setOnClickListener(new OnClickListener()
        {//按钮事件
           public void onClick(View v) {
              // TODO Auto-generated method stub
        	   System.out.println("进来了");
        	   Bitmap src = BitmapFactory.decodeResource(getResources(), R.drawable.img); 
        	   int h = src.getHeight();
        	   int w = src.getWidth();
        	   int temp[] = new int[h*w];
        	   int result[] = new int[h*w];
        	   src.getPixels(temp, 0, w, 0, 0, w, h);
        	   result = LibImgFun.ImgFun(temp, w, h);
        	   System.out.println("成功了");
        	   Bitmap last = Bitmap.createBitmap(w, h, Config.RGB_565);
        	   last.setPixels(result, 0, w, 0, 0, w, h);
        	   imgHuaishi.setImageBitmap(last); 
           }           
        });
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

           LibImgFun.java

package com.example.haveimgfun;

public class LibImgFun {  
static {   
        System.loadLibrary("ImgFun");   
       }   
      /** 
            * @param width the current view width 
            * @param height the current view height 
*/ 
    public static native int[] ImgFun(int[] buf, int w, int h);  
}

右击项目,点击android tools选择add native support,这样会出现一个jni文件夹,我们新建文件如下:
                                                        OpenCVforAndroid应用之银行卡号识别 ------  搞定开发环境
Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)  
OPENCV_CAMERA_MODULES:=off
override OPENCV_INSTALL_MODULES:=on
 OPENCV_LIB_TYPE:=SHARED

OPENCV_LIB_TYPE :=STATIC
$(info ==$(OPENCV_INSTALL_MODULES)==)
include G:/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk


LOCAL_MODULE    := ImgFun
LOCAL_SRC_FILES := ImgFun.cpp

include $(BUILD_SHARED_LIBRARY)

  Application.mk

APP_STL:=gnustl_static
APP_CPPFLAGS:=-frtti -fexceptions 
APP_ABI:=armeabi armeabi-v7a 
APP_PLATFORM := android-8

 ImgFun.cpp

#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
#include <opencv2/opencv.hpp>
using namespace cv;
extern "C" {
JNIEXPORT jintArray JNICALL Java_com_example_haveimgfun_LibImgFun_ImgFun(
JNIEnv* env, jobject obj, jintArray buf, int w, int h);
JNIEXPORT jintArray JNICALL Java_com_example_haveimgfun_LibImgFun_ImgFun(
JNIEnv* env, jobject obj, jintArray buf, int w, int h){
	jint *cbuf;
	cbuf = env->GetIntArrayElements(buf, NULL);
	if(cbuf == NULL)
	{
		return 0;
	}
	Mat myimg(h, w, CV_8UC4, (unsigned char*)cbuf);
	for(int j=0; j<myimg.rows/2; j++)
	{
		myimg.row(j).setTo(Scalar(0, 0, 0, 0));
	}
	int size=w*h;
	jintArray result = env->NewIntArray(size);
	env->SetIntArrayRegion(result, 0, size, cbuf);
	env->ReleaseIntArrayElements(buf, cbuf, 0);
	return result;
	}

}

 至此,环境搭建及测试完毕!

相关推荐

littletit / 0评论 2019-10-20