我的Android使用openCV记录(3)

博主QQ:1356438802

QQ群:473383394——UVC&OpenCV47




四、使用 c++ API开发android,其实也就是做JNI开发:


JNI——java native interface,java本地接口。可以在java类中调用jni函数,而jni函数又以C++的形式调用了openCV库。


这是我成功运行的代码,链接: http://pan.baidu.com/s/1o7FR7lw  密码:bod7

创建工程       

        步骤如工程一,创建新工程GrayProcess2,将lena.jpg添加到资源文件,并按上面所示将opencv类库添加到工程中。

编写上层代码(java)

(1)Stings.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <resources>  
  2.     <string name="app_name">GrayProcess2</string>  
  3.     <string name="hello_world">Hello world!</string>  
  4.     <string name="menu_settings">Settings</string>  
  5.     <string name="title_activity_main">GrayProcess2</string>  
  6.     <string name="str_proc">gray process</string>  
  7.     <string name="str_desc">image description</string>  
  8. </resources>  
(2)main.xml

[html]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  2.     xmlns:tools="http://schemas.android.com/tools"  
  3.     android:orientation="vertical"  
  4.     android:layout_width="match_parent"  
  5.     android:layout_height="match_parent" >  
  6.       
  7.     <Button   
  8.         android:id="@+id/btn_gray_process"  
  9.         android:layout_width="fill_parent"  
  10.         android:layout_height="wrap_content"  
  11.         android:text="@string/str_proc"/>  
  12.       
  13.     <ImageView  
  14.         android:id="@+id/image_view"  
  15.         android:layout_width="wrap_content"  
  16.         android:layout_height="wrap_content"  
  17.         android:contentDescription="@string/str_proc"/>  
  18.   
  19. </LinearLayout>  

(3)MainActivity.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.iron.grayprocess2;  
  2.   
  3. import org.opencv.android.BaseLoaderCallback;  
  4. import org.opencv.android.LoaderCallbackInterface;  
  5. import org.opencv.android.OpenCVLoader;  
  6. import android.os.Bundle;  
  7. import android.app.Activity;  
  8. import android.graphics.Bitmap;  
  9. import android.graphics.BitmapFactory;  
  10. import android.graphics.Bitmap.Config;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14. import android.widget.ImageView;  
  15.   
  16. public class MainActivity extends Activity implements OnClickListener{  
  17.   
  18.     private Button btnProc;  
  19.     private ImageView imageView;  
  20.     private Bitmap bmp;  
  21.       
  22.     //OpenCV类库加载并初始化成功后的回调函数,在此我们不进行任何操作  
  23.      private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {  
  24.         @Override  
  25.         public void onManagerConnected(int status) {  
  26.             switch (status) {  
  27.                 case LoaderCallbackInterface.SUCCESS:{  
  28.                     System.loadLibrary("image_proc");  
  29.                 } break;  
  30.                 default:{  
  31.                     super.onManagerConnected(status);  
  32.                 } break;  
  33.             }  
  34.         }  
  35.     };  
  36.       
  37.     @Override  
  38.     public void onCreate(Bundle savedInstanceState) {  
  39.         super.onCreate(savedInstanceState);  
  40.         setContentView(R.layout.main);  
  41.         btnProc = (Button) findViewById(R.id.btn_gray_process);  
  42.         imageView = (ImageView) findViewById(R.id.image_view);  
  43.         //将lena图像加载程序中并进行显示  
  44.          bmp = BitmapFactory.decodeResource(getResources(), R.drawable.lena);  
  45.         imageView.setImageBitmap(bmp);  
  46.         btnProc.setOnClickListener(this);  
  47.     }  
  48.   
  49.     @Override  
  50.     public void onClick(View v) {  
  51.            
  52.         int w = bmp.getWidth();  
  53.         int h = bmp.getHeight();  
  54.         int[] pixels = new int[w*h];       
  55.         bmp.getPixels(pixels, 0, w, 00, w, h);  
  56.         int[] resultInt = ImageProc.grayProc(pixels, w, h);  
  57.         Bitmap resultImg = Bitmap.createBitmap(w, h, Config.ARGB_8888);  
  58.         resultImg.setPixels(resultInt, 0, w, 00, w, h);  
  59.         imageView.setImageBitmap(resultImg);      
  60.     }  
  61.       
  62.     @Override  
  63.     public void onResume(){  
  64.         super.onResume();  
  65.         //通过OpenCV引擎服务加载并初始化OpenCV类库,所谓OpenCV引擎服务即是  
  66.         //OpenCV_2.4.3.2_Manager_2.4_*.apk程序包,存在于OpenCV安装包的apk目录中  
  67.         OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_3, this, mLoaderCallback);  
  68.     }  
  69. }  

 代码第28行:System.loadLibrary("image_proc")用来当OpenCV类库初始化完成后加载类库image_proc。此类库由我们来生成,用于完成图像灰度处理的操作,此部分将在下面中说明。


  (4) ImageProc.java

[java]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. package com.iron.grayprocess2;  
  2.   
  3. public class ImageProc {  
  4.     public static native int[] grayProc(int[] pixels, int w, int h);  
  5. }  


 ImageProc.java中只定义了方法grayProc,关键字native表明,此方法的实现由本地代码(C/C++)来完成。


编写JNI及C相关代码

        在项目中新建目录jni,在jni目录中分别添加文件Android.mk,Application.mk,ImageProc.h,ImageProc.cpp,这四个文件的内容分别如下所示。

        (1) Android.mk

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. LOCAL_PATH := $(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. include ../OpenCV-SDK/native/jni/OpenCV.mk  
  4. LOCAL_SRC_FILES  := ImageProc.cpp  
  5. LOCAL_MODULE     := image_proc  
  6. include $(BUILD_SHARED_LIBRARY)  

代码说明:

第一行:指明当前编译路径;

第二行:清空变量;

第三行:将OpenCV类库中的编译文件包含进来,如此一来在我们的工程中即可使用OpenCV类库;

第四行:指定需要编译的C++源文件;

第五行:指定编译生成的类库名称;

第六行:调用命令将源文件编译为静态库。

注:第三行指定的路径很关键,当opencv类库与工程路径相关位置发生改变时,此路径也要随之改变。


(2) Application.mk(配置文件)

[plain]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. APP_STL := gnustl_static  
  2. APP_CPPFLAGS := -frtti -fexceptions  
  3. APP_ABI := armeabi-v7a  
  4. APP_PLATFORM := android-8  


(3)ImageProc.cpp

[cpp]  view plain  copy
  在CODE上查看代码片 派生到我的代码片
  1. #include <ImageProc.h>  
  2. #include <opencv2/core/core.hpp>  
  3. #include <string>  
  4. #include <vector>  
  5.   
  6. using namespace cv;  
  7. using namespace std;  
  8.   
  9. JNIEXPORT jintArray JNICALL Java_com_iron_grayprocess2_ImageProc_grayProc(JNIEnv* env, jclass obj, jintArray buf, jint w, jint h){  
  10.     jint *cbuf;  
  11.     cbuf = env->GetIntArrayElements(buf, false);  
  12.     if(cbuf == NULL){  
  13.         return 0;  
  14.     }  
  15.   
  16.     Mat imgData(h, w, CV_8UC4, (unsigned char*)cbuf);  
  17.   
  18.     uchar* ptr = imgData.ptr(0);  
  19.     for(int i = 0; i < w*h; i ++){  
  20.         //计算公式:Y(亮度) = 0.299*R + 0.587*G + 0.114*B  
  21.         //对于一个int四字节,其彩色值存储方式为:BGRA  
  22.         int grayScale = (int)(ptr[4*i+2]*0.299 + ptr[4*i+1]*0.587 + ptr[4*i+0]*0.114);  
  23.         ptr[4*i+1] = grayScale;  
  24.         ptr[4*i+2] = grayScale;  
  25.         ptr[4*i+0] = grayScale;  
  26.     }  
  27.   
  28.     int size=w * h;  
  29.     jintArray result = env->NewIntArray(size);  
  30.     env->SetIntArrayRegion(result, 0, size, cbuf);  
  31.     env->ReleaseIntArrayElements(buf, cbuf, 0);  
  32.     return result;  
  33. }  


说明:

  •         ImageProc.h头文件可以通过jdk提供的工具javah来生成,具体生成方法在下面
  •         JNI中的定义的函数遵循一定的命名规则:Java_包名_类名_方法名,具体参考JNI编程相关知识;
  •         ImageProc.cpp中利用彩色值转换为灰度值的计算公式,将lena.jpg图像的每个像素转换为灰度值,并返回给应用层。需要注意的是对于 ARGB_8888类型的图像而言,其每一个像素值在int型数据中的存储序列为BGRA。
    还需要注ImageProc.cpp 这个文件 第10行的函数名称Java_包名_类名_方法名 请修改成.h 文件生成的那个函数名 
生成.h 文件


1.首先当你写完ImageProc.java 这个保存 以后 eclipse会自动帮你生成 java 的class文件

   你可以再工程目录--》 bin --》classes -》com -------。。。。。 的文件里找到

   比如我的 在E:\work\op\OpenCV-2.4.5-android-sdk\samples\Test2\bin\classes\com\test2\test2 这个路径下

如图


2. 将classes文件拷贝到e盘根目录下

然后打开 cmd 

e:

cd classes

javah com.test2.test2.ImageProc

然后就会在classes文件里找到一个 xxx.的头文件 如图


你可以将这个头文件改成任意名字 比如我们上面的ImageProc.h 然后放入工程目录的jni中


编译运行方法有两种


1.  配置eclipse自动运行

第一步:转换工程。点击“文件 -> 新建 -> 其他”(快捷键:Ctrl+N)。选择“C/C++”下的“Convert to a C/C++ Project(Adds C/C++ Nature)”。进 入“下一步”。


第二步:选中你刚才建的“HelloJni”工程,下面左边选“Makefile project”右边选“Cygwin GCC”。确定后提示的“透视图”不清楚是什么,点击“是”即可。


第三步:在“HelloJni”工程上右键,选择“属性”。配置“C/C++ Build”和“C/C++ General -> Paths and Symbols”。

C/C++ Build:点击“C/C++ Build”,在右边的“Builder Settings”中去掉默认勾选的“Use default build command”复选框。设置Build command为“
${NDKROOT}/ndk-build.cmd "


C/C++ General -> Paths and Symbols:在Includes下add新的GNU C依赖路径。此“HelloJni”工程需要“D:\Java\android-ndk-r8\platforms\android-8\arch-arm\usr\include”即可,以后根据不同项目选择不同的依赖库。


这里只要是你cpp文件里头文件包含目录

你可以直接在NDK 和opencv jni那个目录下搜索头文件名 然后看看在那个路径有

配置好后运行就行了


2.手动使用Cygwin 生成so 然后运行。或者也可以用如何在Android下使用JNI》里面的方法,这是我的方法。

 由于程序中涉及到了JNI编程,因此需要用cygwin对其中的C/C++代码进行编译。打开cygwin,进入到工程的根目录中执行命令:$NDKROOT/ndk-build完成相关编译;之后在eclipse中刷新工程GrayProcess2,运行即可。编译及运行结果分别如下所示。


    



到这里两种Android环境下的openCV使用方法都结束了!

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值