Android调用C++OpenCV程序的方法(NDK+JNI)

参考:   [1] http://blog.csdn.net/donglynn/article/details/23046925 

               [2]http://www.cnblogs.com/devinzhang/archive/2012/02/29/2373729.html

               [3]http://www.tuicool.com/articles/yaeeuu    

               [4]《细说Android4.0 NDK编程》


1.环境搭建

        Android 环境搭建

        OpenCV4Android安装

        安装CDT

        安装Android NDK

        安装Cygwin

        上述安装过程可参考[2]


2.创建Java类,用于加载本地C++文件,声明本地的C++方法

创建Android工程,载入Opencv4Android库。

新建Java类,名为LibImgFun.

package com.example.haveimgfun;

public class LibImgFun {
	static{
                //加载本地C++库文件
		System.loadLibrary("ImgFun");
	}

        //声明本地方法
	public native void canny(long matAddrInRGBA, long matAddroutInRGBA);
}

编写完成后,eclipse会自动编译,在工程\bin\classes\com\example\haveimgfun下产生LibImgFun.class.


3.使用javah工具产生C语言的.h头文件

打开Windows 命令行,进入工程\bin\classes,执行命令javah com.example.haveimgfun.LibImgFun

执行完成后,在工程\bin\classes文件夹下产生com_example_haveimgfun_LibImgFun.h文件,在工程目录下新建jni文件夹,将.h文件移到jni文件夹中。

       下面是.h文件的内容

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_example_haveimgfun_LibImgFun */

#ifndef _Included_com_example_haveimgfun_LibImgFun
#define _Included_com_example_haveimgfun_LibImgFun
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_haveimgfun_LibImgFun
 * Method:    processImg
 * Signature: (JJ)V
 */
JNIEXPORT void JNICALL Java_com_example_haveimgfun_LibImgFun_canny
  (JNIEnv *, jobject, jlong, jlong);

#ifdef __cplusplus
}
#endif
#endif

4.编写cpp程序

根据.h的定义,编写cpp程序,程序对图片执行canny运算,留意代码中的格式转换,程序将Mat的地址作为参数,用了long到指针的强转。

#include 
#include 
 
JNIEXPORT void JNICALL Java_com_example_haveimgfun_LibImgFun_canny
   ( JNIEnv * , jobject , jlong addrInRGBA , jlong addrOut ) {
     cv :: Mat * pMatInRGBA = ( cv :: Mat * ) addrInRGBA ;
     cv :: Mat * pMatOut = ( cv :: Mat * ) addrOut ;
     cv :: Mat imageGray ;
     cv :: cvtColor ( * pMatInRGBA , imageGray , CV_RGBA2GRAY ) ;
     cv :: Canny ( imageGray , * pMatOut , 30 , 90 ) ;
}


5.编写Android.mk和Application.mk作为ndk-build的makefile

Android.mk和Application.mk可以在ndk安装目录\samples\hello-jni\jni文件夹中找到,复制到工程\jni中。

Android.mk:

# Copyright (C) 2009 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

include D:/OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk

LOCAL_MODULE    := ImgFun		
LOCAL_SRC_FILES := com_example_haveimgfun_LibImgFun.cpp

include $(BUILD_SHARED_LIBRARY)
其中,LOCAL_MODULE后面的ImgFun是最终产生的.so文件的名字,应该与LibImgFun.java中 System.loadLibrary("ImgFun");的引号中的内容一致。
Application.mk:

APP_STL:=gnustl_static  
APP_CPPFLAGS:=-frtti -fexceptions  
APP_ABI:=armeabi armeabi-v7a 

6.编译cpp程序

写好上述两个文件之后,在jni/目录下执行 <mdk_path>/ndk-build (将 <ndk_path> 改为ndk的安装路径)。顺利的话,可以看到输出信息最后一行:

1
[  armeabi  -  v7a  ]  Install            :  libprocess_frame  .  so  =  >  libs  /  armeabi  -  v7a  / libprocess_frame  .  so

说明已经编译成功了。

7.编写MainActivity,执行程序

package com.example.haveimgfun;

import org.opencv.android.BaseLoaderCallback;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

//opencv
import org.opencv.android.BaseLoaderCallback;  
import org.opencv.android.LoaderCallbackInterface;  
import org.opencv.android.OpenCVLoader;  
import org.opencv.android.Utils;  
import org.opencv.core.Mat;  
import org.opencv.imgproc.Imgproc;  

import com.example.haveimgfun.R;


public class MainActivity extends Activity {
	
	private Button button;
	private ImageView image; 
	private Bitmap bmp;
	private TextView text;
	
	//Opencv加载
	
	private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this){
		@Override
		public void onManagerConnected(int status) {
			switch (status) {  
				case LoaderCallbackInterface.SUCCESS:{ 
					System.out.println("load opencv sucess");
				} break;  
				default:{  
					super.onManagerConnected(status);  
				} break;  
			}  
		}
	};
			
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		image = (ImageView)findViewById(R.id.ImageView);
		button = (Button)findViewById(R.id.button);
		text = (TextView)findViewById(R.id.text);
		
		ButtonListener buttonListener = new ButtonListener();
		button.setOnClickListener(buttonListener);
		//graph
		bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
		image.setImageBitmap(bmp);
		text.setText("code ok!");
	}

	class ButtonListener implements OnClickListener{

		@Override
		public void onClick(View v) {
			text.setText("button is pressed!");
			Mat rgbMat = new Mat();
			Mat resultMat = new Mat();
			Utils.bitmapToMat(bmp, rgbMat); 
			
			text.setText("row: "+rgbMat.rows()+" col:"+rgbMat.cols()+" channels: "+rgbMat.channels());
			
			//load c++
			LibImgFun libimagefun = new LibImgFun();
			
			libimagefun.canny(rgbMat.getNativeObjAddr(),resultMat.getNativeObjAddr());
			
			text.setText("canny OK!");
			Utils.matToBitmap(resultMat, bmp); 
            image.setImageBitmap(bmp);  
		}
	}
	
	@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 void onResume(){
		super.onResume();
		OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9, this, mLoaderCallback);
	}

}

activity_main.xml



    
    
    


程序运行结果

Android调用C++OpenCV程序的方法(NDK+JNI)_第1张图片

点击按钮后

Android调用C++OpenCV程序的方法(NDK+JNI)_第2张图片


你可能感兴趣的:(opencv,Android)