Android开发项目中使用OpenCV库
本教程的创建旨在帮助您在Android项目中使用OpenCV库。
本指南是用Windows 7编写的,虽然它应该与OpenCV4Android SDK支持的任何其他操作系统配合使用。
本教程假设您已经安装并配置了以下内容:
- JDK
- Android SDK和NDK
- Eclipse IDE
- Eclipse的ADT和CDT插件
如果您需要上述任何方面的帮助,您可以参考我们的Android开发入门指南。
本教程还假定您的开发机器上已经安装了OpenCV4Android SDK,并且相应地在测试设备上安装了OpenCV Manager。如果您需要任何帮助,可以咨询我们的OpenCV4Android SDK教程。
如果您在彻底按照这些步骤后遇到任何错误,请随时通过W3Cschool官方或OpenCV Q&A论坛与我们联系。我们将竭尽全力帮助您。
在您的Android项目中使用OpenCV库
在本节中,我们将介绍如何使一些现有项目使用OpenCV。从Android 2.4.2版本开始,OpenCV Manager用于为应用程序提供最佳可用版本的OpenCV。
Java的
应用程序开发与异步初始化
使用异步初始化是应用程序开发的推荐方法。它使用OpenCV Manager来访问目标系统中外部安装的OpenCV库。
1、将OpenCV库项目添加到您的工作区。在工作区中使用菜单File - > Import - > Existing project。
按浏览按钮,找到OpenCV4Android SDK(OpenCV-2.4.9-android-sdk/sdk)。
2、在项目 - >属性 - > Android - >库 - >添加选择OpenCV库 - 2.4.9中的应用程序项目中添加对OpenCV Java SDK的引用。
在大多数情况下,OpenCV Manager可能会从Google Play自动安装。对于这种情况,当Google Play不可用时,即仿真器,开发板等,您可以使用adb工具手动安装。看Manager Selection详情。
有一个非常基础的代码片段实现异步初始化。它显示基本原则。有关详细信息,请参阅“15拼图”OpenCV示例。
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的本机库。在OpenCV成功初始化之后,加载自己的依赖于OpenCV的本地库。默认BaseLoaderCallback实现将应用程序上下文视为Activity,并在初始化失败的情况下调用Activity.finish()方法退出。要覆盖此行为,您需要覆盖BaseLoaderCallback类的finish()方法,并实现您自己的finalization方法。
静态初始化应用开发
根据这种方法,所有OpenCV二进制文件都包含在应用程序包中。它主要用于开发目的。对于生产代码,不建议使用此方法,因此推荐使用发行包,通过上述异步初始化与OpenCV Manager进行通信。
1、将OpenCV库项目添加到工作空间中,与上述异步初始化相同。使用菜单文件 - >导入 - >工作区中的现有项目,按浏览按钮并选择OpenCV SDK路径(OpenCV-2.4.9-android-sdk/sdk
)。
2、在应用程序项目中,在项目 - >属性 - > Android - >库 - > Add中添加OpenCV4Android SDK的参考选择OpenCV Library - 2.4.9;
3、如果您的应用程序项目没有JNI部分,只需将相应的OpenCV本机库从<OpenCV-2.4.9-android-sdk>/sdk/native/libs/<target_arch>您的项目目录复制到文件夹即可libs/<target_arch>。
在具有JNI部分的应用程序项目的情况下,而不是手动库复制,您需要修改您的Android.mk文件:在“include $(CLEAR_VARS)”之后添加以下两个代码行,然后在“include path_to_OpenCV-2.4.9 -Android-SDK / SDK /本地/ 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
之后,libs在JNI build.v期间,OpenCV库将被复制到您的应用程序文件夹
Eclipse将自动将libs文件夹中的所有库包含到应用程序包(APK)中。
4、在应用程序中启用OpenCV的最后一步是调用OpenCV API之前的Java初始化代码。例如,可以在Activity类的静态部分中完成:
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++
要构建您自己的Android应用程序,使用OpenCV作为本机部分,应采取以下步骤:
- 您可以使用环境变量来指定OpenCV包的位置,也可以在jni/Android.mk项目中硬编码绝对或相对路径。
- 该文件jni/Android.mk应使用通用规则此文件的当前应用程序被写入。有关详细信息,请参阅文件中的Android NDK归档的Android NDK文档<path_where_NDK_is_placed>/docs/ANDROID-MK.html。
- 以下行:
include C:\Work\OpenCV4Android\OpenCV-2.4.9-android-sdk\sdk\native\jni\OpenCV.mk
应在此行后插入jni/Android.mk
文件:
include $(CLEAR_VARS)
4、OpenCV Manager 可以使用多个变量来定制OpenCV,但是当您的应用程序通过OpenCV Manager API使用异步初始化时,您无需使用它们。
- 注意
- 这些变量应该在“include ... / OpenCV.mk”行之前设置:
OPENCV_INSTALL_MODULES:=on
将必要的OpenCV动态库复制到项目libs文件夹中,以便将它们包含在APK中。
OPENCV_CAMERA_MODULES:=off
跳过本机OpenCV相机相关的libs复制到项目libs文件夹。
OPENCV_LIB_TYPE:=STATIC
执行与OpenCV的静态链接。默认使用动态链接,项目JNI lib依赖于libopencv_java.so。
5、该文件Application.mk应该存在并应包含行:
APP_STL:= gnustl_static
APP_CPPFLAGS:= -frtti -fexceptions
另外,像这样的一行:
APP_ABI:= armeabi-v7a
应该指定应用程序目标平台。
在某些情况下,根据OpenCV构建应用程序JNI库时,会发生链接错误(如“函数”cv :: toUtf16(std :: basic_string <...> ...未定义的引用“mbstowcs”)以下行Application.mk通常会修复它:
APP_PLATFORM:= android-9
6、或者使用手动的 ndk-build调用或者设置Eclipse CDT Builder来构建本地JNI库,然后(重新)构建Java部分并创建一个APK。
Hello OpenCV Sample
以下是引导您创建简单的以OpenCV为中心的应用程序的过程的基本步骤。它将能够访问摄像机输出,处理和显示结果。
- 打开Eclipse IDE,创建一个新的干净工作区,创建一个新的Android项目文件 - >新建 - > Android项目
- 相应地设置名称,目标,包和minSDKVersion。使用OpenCV4Android SDK构建的最小SDK版本为11.最小设备API级别(应用程序清单)为8。
- 允许Eclipse创建默认活动。让我们将活动命名为HelloOpenCvActivity。
- 选择全屏布局的空白活动。让我们命名布局HelloOpenCvLayout。
- 将OpenCV库项目导入到您的工作区。
- 在项目属性中引用OpenCV库。
- 将您的布局文件编辑为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 >
- 将以下权限添加到
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” />
- 在AndroidManifest.xml中设置应用程序主题以隐藏标题和系统按钮。
<application
android:icon="@drawable/icon"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
- 将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);
}
- 定义您的活动实现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();
}
- 在设备或模拟器上运行应用程序。
让我们讨论一些最重要的步骤。每个使用UI的Android应用程序都必须实现活动和查看。通过第一步,我们创建空白活动和默认视图布局。最简单的以OpenCV为中心的应用程序必须实现OpenCV初始化,创建自己的视图来显示来自相机的预览,并实现CvCameraViewListener2接口从相机获取帧并处理它。
首先,我们使用xml布局创建我们的应用程序视图。我们的布局由org.opencv.android.JavaCameraView类中唯一的全屏组件组成。这个类在OpenCV库中实现。它继承自CameraBridgeViewBase,它扩展了SurfaceView并使用了标准的Android相机API。
创建布局后,我们需要实现Activity类。OpenCV初始化过程已经在上面讨论过了。在本例中,我们使用异步初始化。CvCameraViewListener接口的实现允许您在从相机抓取并在屏幕上渲染之前添加处理步骤。最重要的功能是onCameraFrame。它是回调函数,它在从摄像机检索帧时被调用。回调输入是表示来自相机的帧的CvCameraViewFrame类的对象。
注意 不要保存或使用CvCameraViewFrame对象从onCameraFrame回调。这个对象没有自己的状态,它的回调行为是不可预测的!
它具有rgba()和gray()方法,可以分别获取帧为RGBA和一个通道灰度Mat。它期望onCameraFrame函数返回将在屏幕上绘制的RGBA帧。