我的Android使用openCV记录(3)

博主QQ:1356438802

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

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

创建工程

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

编写上层代码(java)

(1)Stings.xml

[html] view
plain
 copy

  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

  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. <Button
  7. android:id="@+id/btn_gray_process"
  8. android:layout_width="fill_parent"
  9. android:layout_height="wrap_content"
  10. android:text="@string/str_proc"/>
  11. <ImageView
  12. android:id="@+id/image_view"
  13. android:layout_width="wrap_content"
  14. android:layout_height="wrap_content"
  15. android:contentDescription="@string/str_proc"/>
  16. </LinearLayout>

(3)MainActivity.java

[java] view
plain
 copy

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

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

(4) ImageProc.java

[java] view
plain
 copy

  1. package com.iron.grayprocess2;
  2. public class ImageProc {
  3. public static native int[] grayProc(int[] pixels, int w, int h);
  4. }

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

  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

  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

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

说明:

  •         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使用方法都结束了!

时间: 2024-10-14 07:16:56

我的Android使用openCV记录(3)的相关文章

我的Android使用openCV记录(2)

博主QQ:1356438802 二.opecnv for android 开发环境搭建: opencv for android SDK 安装: 进入官网(http://opencv.org/)下载OpenCV4Android并解压,其目录结构如下: 其中, (1). sdk目录即是我们开发opencv所需要的类库: (2). samples目录中存放着若干opencv应用示例(包括人脸检测等),可为我们进行android下的opencv开发提供参考: (3). doc目录为opencv类库的使用

我的Android使用openCV记录(1)

博主QQ:1356438802 前面的文章我已经说了,我的最终目的是要在Android上应用openCV. 刚开始我在Ubuntu虚拟机上搭建了openCV的开发环境,可是虚拟机太卡,我又换到windows下,搭建QT开发环境. 经过两个平台的折腾,我已经对openCV的开发环境滚瓜烂熟了.现在我要在Android上run openCV的应用!!! 耶! start...(其实我这篇文章也是参考别人的来操作,不过我的方法更简单些!) 一.首先要搭建windows平台的安卓开发环境 这一步呢,其实

【Android实战】记录自学自定义GifView过程,能同时支持gif和其他图片!【实用篇】

之前写了一篇博客,<[Android实战]记录自学自定义GifView过程,详解属性那些事![学习篇]> 关于自定义GifView的,详细讲解了学习过程及遇到的一些类的解释,然后完成了一个项目,能通过在xml加入自定义 view (MyGifView)中加入自定义属性(my:gif_src = "@drawable/coffee"),达到播放gif图片的效果. 但是,有几个问题 1.gif_src 属性只支持 gif 图,并不支持其他类型的图片 2.只支持默认的引用图片,不

android的入门记录(一)

---恢复内容开始--- 首先,这是我人生中的第一篇博客,也许严格意义上它并不算是一篇博客,但也代表着一些东西. 前言 我们往往在开始学习一门新的语言或者课程时会遇见各式各样的问题,比如说:环境搭建遇到问题,资源不知道去哪里下载,代码令人无法下手,甚至不知道如何运行. 于是便产生了这样的一篇文章--关于我Android入门的记录,以及各式各样问题的解决. 首先从资源的寻找说起. 第一节 开发环境的搭建 Android开发首先需要搭建运行环境,它们分别为 1.JDK:Java开发工具包,因为安卓使

Android 使用OpenCV之编译环境非CygWin方式(Win7+Eclipse+ADT+CDT+NDK)

本文完全基于官网: https://dl-ssl.google.com/android/eclipse/ 只有简单的三步,官网写的非常简明全面,非常佩服 [准备] 1. Eclipse(Indigo) 2. ADT: 这个不说了,无非就是eclipse添加个android的安装源,如果这里选择了NDK Plugin的话,就会自动安装CDT哟: 3. NDK(android-ndk-r9d-windows-x86_64) 地址: http://developer.android.com/tools

记:Android 服务站 问题记录与解决方案

1.dnsmasq域名劫持失败: 现象: 开启wifi热点后确实执行了dnsmasq命令,但是域名劫持失败. 原因: wifi热点开启命令执行后直接执行了dnsmasq命令,当热点开启过程时间很短时域名劫持可以成功:但是启动稍慢即会被系统启动的dnsmasq命令给杀掉并覆盖:所以会导致无效. 解决方案: 开启dnsmasq前定时检查wifi热点是否已经开启成功,成功后再kill掉系统启动的dnsmasq进程,再使用自定义的配置文件执行dnsmasq命令. 2.wifi热点启动频繁失败: 现象:

【Android实战】记录自学自己定义GifView过程,能同一时候支持gif和其它图片!【有用篇】

之前写了一篇博客.<[Android实战]记录自学自己定义GifView过程,具体解释属性那些事! [学习篇]> 关于自己定义GifView的,具体解说了学习过程及遇到的一些类的解释,然后完毕了一个项目,能通过在xml增加自己定义 view (MyGifView)中增加自己定义属性(my:gif_src = "@drawable/coffee").达到播放gif图片的效果. 可是.有几个问题 1.gif_src 属性仅仅支持 gif 图,并不支持其它类型的图片 2.仅仅支持

arcgis android 图上记录gps轨迹

原文  arcgis android 图上记录gps轨迹 public class MainActivity extends Activity { MapView mMapView; LocationDisplayManager lDisplayManager = null; GraphicsLayer gpsGraphicsLayer; Polyline mPolyline; int pointCount = 0; @Override protected void onCreate(Bundl

android常用工具记录

ActionBarSherlock:actionbar统一Api,独立于android各个版本,扩展于support library. 网址:http://actionbarsherlock.com/ android常用工具记录,码迷,mamicode.com