Android调用C++OpenCV程序的方法(NDK+JNI)
2015-08-03 21:06
726 查看
参考: [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.
编写完成后,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文件的内容
4.编写cpp程序
根据.h的定义,编写cpp程序,程序对图片执行canny运算,留意代码中的格式转换,程序将Mat的地址作为参数,用了long到指针的强转。
5.编写Android.mk和Application.mk作为ndk-build的makefile
Android.mk和Application.mk可以在ndk安装目录\samples\hello-jni\jni文件夹中找到,复制到工程\jni中。
Android.mk:
Application.mk:
6.编译cpp程序
写好上述两个文件之后,在jni/目录下执行 <mdk_path>/ndk-build (将 <ndk_path> 改为ndk的安装路径)。顺利的话,可以看到输出信息最后一行:
说明已经编译成功了。
7.编写MainActivity,执行程序
activity_main.xml
程序运行结果
点击按钮后
[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 <jni.h> /* 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 <com_example_haveimgfun_LibImgFun.h> #include <opencv2/opencv.hpp> 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<span style="white-space:pre"> </span> 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
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent" > <TextView android:id="@+id/text" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="hello" /> <Button android:id="@+id/button" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="使用C++OpenCV处理图像" /> <ImageView android:id="@+id/ImageView" android:layout_width="fill_parent" android:layout_height="fill_parent" /> </LinearLayout>
程序运行结果
点击按钮后
相关文章推荐
- c++的可视化计算器
- Calculation Of Polynomial(多项式的运算) C++
- 【c++】虚基类
- C++中cin和cin.getline函数连用的问题
- POJ1125Floyd-warshall算法模板题
- C语言深度解剖——读书笔记-12、内存管理
- 《C++编程思想》 第十章 引用和拷贝构造函数(原书代码+知识点+习题+解答)
- C++ 智能指针详解
- 今天在网上看到一个百度的C++面试题目
- JNI_最简单的Java调用C/C++代码(自己整理)
- c++11 中的 move 与 forward
- QString、string相互转换
- C++11 标准新特性: 右值引用与转移语义
- c++实现基于单进程单客户编程模型的echo程序
- 动态规划之UNIMODAL PALINDROMIC DECOMPOSITIONS
- C++中this指针的用法.
- C++零碎知识点
- C语言笔记
- IOS使用纯C语言创建静态库
- C语言-变量的存储类别(auto, static, register, extern)