The exam and travel a while ago kept me away from blogging for a long time. Now that the winter vacation is over, it's time to write and watch something new!
Previously, I mainly focused on the application of OpenCV-based machine learning algorithms in image recognition processing. Of course, these technologies (such as bank card number recognition) will eventually be applied to real life. Let's take bank card number recognition as an example, the most used WeChat actually has this function. Do you see a camera-like button on the right side of the input box when you open your WeChat wallet and bind a bank card? That is where the bank card number recognition function is implemented. Now we also imitate WeChat and port opencv machine learning to android.
This app was made by me in a short amount of time and aims to :
1. Learn more about android programming
2. Understand the process of porting opencv to android to facilitate development
3. Understand the process of porting C++ to android to facilitate development
The main functions of this simple app that I want to accomplish are:
1. Identify the bank card number (tentatively ABC) through the existing photos (bank card) in the mobile phone album
2. Obtain the bank card picture to identify the bank card number by taking a photo of the mobile phone (tentatively ABC)
Due to the short development time and relatively simple implementation, I mainly want to integrate the results as soon as possible. I will use two or three blogs to summarize the main technical points, followed by the first part:
First, get the development environment
(1) OpenCVforAndroid
Environment construction
1> eclipse for android (recommended to download adt-bundle-windows directly)
Java is the most mainstream language for android programming now, and eclipse is an essential programming environment. Now there are many eclipses with adt plug-ins on the Internet. Of course, you can also download the adt plug-in and configure it under eclipse. Endless convenience.
2> Import OpenCV Library
Download the latest OpenCVforAndroid from the OpenCV official website and unzip it to the disk where the workspace is located;
Enter eclipse, import OpenCV Library (right-click in the project column and select Import);
select the option selected in the above figure
Select ...\OpenCV-android-sdk\sdk to import OpenCV into Eclipse.
Import successful!
test program
1>Create a new android application project
2> Import OpenCV Library, right-click the project, click "Bulid Path", select configure build path, and add the OpenCV Library we imported.
3> Programming verification: click the button, grayscale the picture
<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"; //Callback function after the OpenCV library is loaded and initialized successfully 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, "Successfully loaded" ); break ; default : super .onManagerConnected(status); Log.i(TAG, "Load failed" ); 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) {//Get the picture in the res folder and get the bmp picture 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); } }
Result:
Reference: http://blog.csdn.net/yanzi1225627/article/details/16917961
(2) Java's C++ interface --------JNI
Environment construction
In many cases, developers have already developed opencv with C++ and want to use it directly on the mobile terminal. At this time, it is very troublesome to use opencvforandroid. Here we can use the JNI interface in Java to directly call the C++ code.
Required tools : On the basis of (1), you only need to install NDK (version r8 and above) (Note: Now most of your searches on Baidu are still written as NDK+Cygwin, but in fact the new version of NDK (r8 and above, I use r10 version) does not need to download Cygwin. Friends who have downloaded it know that this thing is very pitiful. I downloaded it all night and didn't download it well)
After downloading and installing NDK, refer to http://jingyan.baidu.com/article/5d6edee22d908799eadeec9f.html to configure NDK.
Programming test:
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() {//Button event public void onClick(View v) { // TODO Auto-generated method stub System.out.println("come in"); 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("success"); 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); }
Right-click the project, click android tools and select add native support, a jni folder will appear, and our new file is as follows:
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, jitArray buf, int w, int h); JNIEXPORT jintArray JNICALL Java_com_example_haveimgfun_LibImgFun_ImgFun( JNIEnv * env, jobject obj, jitArray buf, int w, int h) { jin * 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; } }
At this point, the environment construction and testing are completed!