OpenCV的Android开发

OpenCV的Android开发

该教程会教会您在Android项目中如何使用OpenCV库。
教程在Windows 7环境编写,当然可以运行在OpenCV For Android SDK所支持的其他操作系统之上。
该教程假设您已经完成了如下的安装和配置:

  • JDK
  • Android SDK and NDK
  • Eclipse IDE
  • ADT and CDT plugins for Eclipse

如果你需要上述环境搭建、配置的帮助,你可以参考《Android开发介绍》。

该教程还会假设你已经在你的电脑上安装了OpenCV For Android,并且OpenCV Manager已经运行在你的测试设备上了。如果你需要这方面的帮助你参考《OpenCV For Android SDK》。

如果在实践下面的教程中出了问题,你可以通过OpenCV For Android 讨论组联系我们,或这OpenCV通过Q&A forum。我们会尽快的为您解决问题。

在你的Android项目中使用OpenCV库

Java

程序开发中使用异步初始化

在应用开过过程中异步初始化是被推荐使用的一个初始化方式。它通过OpenCV Manager来访问安装在目标系统中的OpenCV库。

  1. 添加OpneCV项目到你的workspace中。菜单File -> Import -> Existing project in your workspace。
    点击浏览按钮定位到OpenCV4Android SDK(OpenCV-2.4.9-android-sdk/sdk)。
    这里写图片描述

  2. 在程序内添加一个OpenCV Java SDK的关联(reference)Project -> Properties -> Android -> Library -> Add select OpenCV Library-2.4.9。
    这里写图片描述

在大多数情况下OpenCV Manager可能已经通过你的Google Play进行了自动安装。另外一种情况就是Google Play没有被安装,或者模拟器、开发板。你可以通过adb工具进行手动安装。
这段代码很简单的实现了异步初始化。详细参看sample ‘15-puzzle’

public class Sample1Java extends Activity implements CvCameraViewListener {
    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                    mOpenCvCameraView.enableView();
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
    @Override
    public void onResume()
    {
        super.onResume();
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback);
    }
    ...
}

在这种情况下应用程序的工作通过OpenCV Manager异步完成。当初始化完成之后,回调OnManagerConnected会被UI线程调用。请注意回调返回之前,不允许调用OpenCV和OpenCV本地依赖。OpenVC初始化完成之后,在加载依赖于OpenCV的本地库。默认情况下BaseLoaderCallback实现需要使用Activity的Context来创建,因为在初始化失败的时候会调用 Activity.finish()方法。撤销这行为你需要重写BaseLoaderCallback 类中的finish()方法,实现你自己的完成方法。

程序开发中使用静态初始化

根据这个方式所有的OpenCV库都需要包含在你应用程序中。它的设计主要是以开发为目的,这种方式是过时的代码生产方式,发布的包推荐使用上述方式,去链接OpenCV Manager实现异步初始化。

  1. 使用与异步初始化相同的方式添加OpenCV库项目到你的workspace里面。用户菜单File->Import->Existing project in your workspace,点击浏览按钮选择OpenCV SDK的路径 在 (Opencv-2.4.9-android-sdk/sdk)。这里写图片描述

  2. 在程序内添加一个OpenCV Java SDK的关联(reference)Project -> Properties -> Android -> Library -> Add select OpenCV Library-2.4.9。这里写图片描述

  3. 如果你的应用程序不包含JNI部分,在<OpenCV-2.4.9-android-sdk>/sdk/native/libs/<target_arch>拷贝相应的OpenCV本地库到你项目的libs/<target_arch>
    在项目包含JNI part的情况,取代手动拷贝你需要修改你的Android.mk文件:在"include $(CLEAR_VARS)"后面,和在` “include path_to_OpenCV-2.4.9-android-sdk/sdk/native/jni/OpenCV.mk”签名添加如下两行代码。
 OPENCV_CAMERA_MODULES:=on
 OPENCV_INSTALL_MODULES:=on

修改完成后应该类似于下面这样:

include $(CLEAR_VARS)

# OpenCV
OPENCV_CAMERA_MODULES:=on
OPENCV_INSTALL_MODULES:=on
include ../../sdk/native/jni/OpenCV.mk

在JNI build期间OpenCV库将被拷贝到你程序的libs目录,Eclipse会自动的将这些库放在APK中。

  1. 最后一步是在应用程序调用OpenCV API之前,在Java代码中开启OpenCV。这是一个例子,在Activity类的static段里面:
static {
    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    }
}

如果你的应用程序包含其他OpenCV依赖的本地库,你应当先加载他们,再初始化OpenCV。

static {
    if (!OpenCVLoader.initDebug()) {
        // Handle initialization error
    } else {
        System.loadLibrary("my_jni_lib1");
        System.loadLibrary("my_jni_lib2");
    }
}

Native/C++

将OpenCV作为你应用程序的一部分来编译Android程序,应采用一下的步骤:

  1. 你可以使用一个环境变量指定你的OpenCV的位置,或者在jni/Android.mk中将相对地址或者绝对地址写死。
  2. 使用共同的规则,文件jni/Android.mk为现在的程序而写。详细信息参看Android NDK文档,该文档在<path_where_NDK_is_placed>/docs/ANDROID-MK.html
  3. 这面这行
include C:\Work\OpenCV4Android\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk

应当插入到jni/Android.mk文件的这一行之后:

include $(CLEAR_VARS)
  1. OpenCV有多个自定义变量,当你使用OpenCV Manager API进行异步加载的时候,并不需要使用他们。

提示:这个变量应当设置在”include …/OpenCV.mk”之前:
OPENCV_INSTALL_MODULES:=on

拷贝所需要的OpenCV动态库到项目libs目录中,因为APK需要包含他们。

OPENCV_CAMERA_MODULES:=off

不将OpenCV camera发布的库拷贝到项目目录。

OPENCV_LIB_TYPE:=STATIC

执行静态链接OpenCV。默认的是动态链接,项目的JNI会依赖于libopencv_java.so.
5. Application.mk应当存在,并且需要包含下面这几行:

 APP_STL := gnustl_static
 APP_CPPFLAGS := -frtti -fexceptions

像这样一行:

 APP_ABI := armeabi-v7a

需要指定应用程序的目标平台。
当编译应用程序的时候,JNI库会出现链接错误,例如:(like "In function 'cv::toUtf16(std::basic_string<...>... undefined reference to 'mbstowcs'")。Application.mk里面的这一行就可以对其修正:

 APP_PLATFORM := android-9
  1. 无论使用ndk-build手册调用还是安装Eclipse CDT Builder来编译本地JNI库,编译java部分,都会创建一个APK。

Hello OpenCV Sample

这里是一个基础教程,指导你创建一个OpenCV-centric应用程序的simple。他能访问照相机的输出,执行它并显示出来。

  1. 打开Eclipse IDE创建一个干净的workspace,创建一个Android项目File->New->Android Project。
  2. 设置名称、目标、包名和minSDK版本。OpenCV4AndroidSDK支持的最低Android编译版本是11.最低设备API版本是8.
  3. 允许Eclipse图创建默认的activity。将Activity名称定义为HelloOpenCvActivity。
  4. 选择Blank Activity全屏layout。设置layout的名称为HelloOpenCvLayout。
  5. 引入OpenCV库到你的项目workspace中。
  6. 关联OpenCV库到你的项目属性中。
    这里写图片描述
  7. 编译你的layout xml文件并且粘贴如下的内容:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       xmlns:tools="http://schemas.android.com/tools"
      xmlns:opencv="http://schemas.android.com/apk/res-auto"
      android:layout_width="match_parent"
      android:layout_height="match_parent" >
    
       <org.opencv.android.JavaCameraView
           android:layout_width="fill_parent"
           android:layout_height="fill_parent"
           android:visibility="gone"
           android:id="@+id/HelloOpenCvView"
           opencv:show_fps="true"
           opencv:camera_id="any" />
    
    </LinearLayout>
  8. 在AndroidManifest.xml文件中添加如下权限:

    </application>
    
    <uses-permission android:name="android.permission.CAMERA"/>
    <uses-feature android:name="android.hardware.camera" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front" android:required="false"/>
    <uses-feature android:name="android.hardware.camera.front.autofocus" android:required="false"/>
  9. 在AndroidManifest.xml中设置应用程序的风格,隐藏title和系统按钮。

    <application
       android:icon="@drawable/icon"
       android:label="@string/app_name"
       android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
  10. 在Activity中添加OpenCV库的初始化。

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
    @Override
    public void onManagerConnected(int status) {
        switch (status) {
            case LoaderCallbackInterface.SUCCESS:
            {
                Log.i(TAG, "OpenCV loaded successfully");
                mOpenCvCameraView.enableView();
            } break;
            default:
            {
                super.onManagerConnected(status);
            } break;
        }
    }
    };
    @Override
    public void onResume()
    {
    super.onResume();
    OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_6, this, mLoaderCallback);
    }
  11. 你的Activity类需要实现CvCameraViewListener2接口YourActivity extends Activity implements CvCameraViewListener2,onCreate、onDestroy、onPause实现下面的代码。

    private CameraBridgeViewBase mOpenCvCameraView;
    @Override
    public void onCreate(Bundle savedInstanceState) {
    Log.i(TAG, "called onCreate");
    super.onCreate(savedInstanceState);
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
    setContentView(R.layout.HelloOpenCvLayout);
    mOpenCvCameraView = (CameraBridgeViewBase) findViewById(R.id.HelloOpenCvView);
    mOpenCvCameraView.setVisibility(SurfaceView.VISIBLE);
    mOpenCvCameraView.setCvCameraViewListener(this);
    }
    @Override
    public void onPause()
    {
    super.onPause();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
    }
    public void onDestroy() {
    super.onDestroy();
    if (mOpenCvCameraView != null)
        mOpenCvCameraView.disableView();
    }
    public void onCameraViewStarted(int width, int height) {
    }
    public void onCameraViewStopped() {
    }
    public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
    return inputFrame.rgba();
    }
  12. 运行你的用于程序。

    来讨论一下非常重要的步骤。每个Android程序必须实现Activity和View。在第一步我们创建了Blank Activity并且定义了view的layout。OpenCV-centric必须实现OpenCV的初始化,创建自己的view来预览相机并且实现CvCameraViewListener2接口来获取相机的帧数据。

    首先我们创建了我们自己的应用程序,view使用layout。我自己的layout内容仅仅是一个全屏的组件类org.opencv.android.JavaCameraView. 。这个类通过OpenCV library来实现。它继承CameraBridgeViewBase,extends SurfaceView 使用Android的相机API。

然后创建了laoyout我们需要实现Activity类。OpenCV的初始化在上面已经讨论过了。在这个sample里面使用了异步初始化。实现CvCameraViewListener接口,允许你添加执行抓取帧数据,并且将数据显示在屏幕上。必须实现函数onCameraFrame。它是一个回调函数,并且它会取回相机的帧数据。回调的输入对象是CvCameraViewFrame类。

提示 不要保存或者使用CvCameraViewFrame对象的onCameraFrame回调。这个对象没有它自己的状态和行为。

它有rgba()和gray()方法允许得到RGBA帧数据,和一个灰度通道的Mat。它希望通过onCameraFrame方法返回RGBA真,这样就可以绘制到屏幕上了。

出处:http://docs.opencv.org/master/d5/df8/tutorial_dev_with_OCV_on_Android.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值