Android開發(fā)項目中使用OpenCV庫

2018-08-26 10:47 更新

本教程的創(chuàng)建旨在幫助您在Android項目中使用OpenCV庫。

本指南是用Windows 7編寫的,雖然它應該與OpenCV4Android SDK支持的任何其他操作系統(tǒng)配合使用。

本教程假設您已經(jīng)安裝并配置了以下內(nèi)容:

  • JDK
  • Android SDK和NDK
  • Eclipse IDE
  • Eclipse的ADT和CDT插件

如果您需要上述任何方面的幫助,您可以參考我們的Android開發(fā)入門指南。

本教程還假定您的開發(fā)機器上已經(jīng)安裝了OpenCV4Android SDK,并且相應地在測試設備上安裝了OpenCV Manager。如果您需要任何幫助,可以咨詢我們的OpenCV4Android SDK教程。

如果您在徹底按照這些步驟后遇到任何錯誤,請隨時通過W3Cschool官方或OpenCV Q&A論壇與我們聯(lián)系。我們將竭盡全力幫助您。

在您的Android項目中使用OpenCV庫

在本節(jié)中,我們將介紹如何使一些現(xiàn)有項目使用OpenCV。從Android 2.4.2版本開始,OpenCV Manager用于為應用程序提供最佳可用版本的OpenCV。

Java的

應用程序開發(fā)與異步初始化

使用異步初始化是應用程序開發(fā)的推薦方法。它使用OpenCV Manager來訪問目標系統(tǒng)中外部安裝的OpenCV庫。

1、將OpenCV庫項目添加到您的工作區(qū)。在工作區(qū)中使用菜單File - > Import - > Existing project。

按瀏覽按鈕,找到OpenCV4Android SDK(OpenCV-2.4.9-android-sdk/sdk)。

Android開發(fā)項目中使用OpenCV庫

2、在項目 - >屬性 - > Android - >庫 - >添加選擇OpenCV庫 - 2.4.9中的應用程序項目中添加對OpenCV Java SDK的引用。

Android開發(fā)項目中使用OpenCV庫

在大多數(shù)情況下,OpenCV Manager可能會從Google Play自動安裝。對于這種情況,當Google Play不可用時,即仿真器,開發(fā)板等,您可以使用adb工具手動安裝??碝anager Selection詳情。

有一個非常基礎的代碼片段實現(xiàn)異步初始化。它顯示基本原則。有關詳細信息,請參閱“15拼圖”O(jiān)penCV示例。

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回調(diào)將在UI線程中調(diào)用。請注意,在調(diào)用此回調(diào)之前,不允許使用OpenCV調(diào)用或加載依賴OpenCV的本機庫。在OpenCV成功初始化之后,加載自己的依賴于OpenCV的本地庫。默認BaseLoaderCallback實現(xiàn)將應用程序上下文視為Activity,并在初始化失敗的情況下調(diào)用Activity.finish()方法退出。要覆蓋此行為,您需要覆蓋BaseLoaderCallback類的finish()方法,并實現(xiàn)您自己的finalization方法。

靜態(tài)初始化應用開發(fā)

根據(jù)這種方法,所有OpenCV二進制文件都包含在應用程序包中。它主要用于開發(fā)目的。對于生產(chǎn)代碼,不建議使用此方法,因此推薦使用發(fā)行包,通過上述異步初始化與OpenCV Manager進行通信。

1、將OpenCV庫項目添加到工作空間中,與上述異步初始化相同。使用菜單文件 - >導入 - >工作區(qū)中的現(xiàn)有項目,按瀏覽按鈕并選擇OpenCV SDK路徑(OpenCV-2.4.9-android-sdk/sdk)。

Android開發(fā)項目中使用OpenCV庫

2、在應用程序項目中,在項目 - >屬性 - > Android - >庫 - > Add中添加OpenCV4Android SDK的參考選擇OpenCV Library - 2.4.9;

Android開發(fā)項目中使用OpenCV庫

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

結(jié)果應如下所示:

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的最后一步是調(diào)用OpenCV API之前的Java初始化代碼。例如,可以在Activity類的靜態(tài)部分中完成:

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++

要構(gòu)建您自己的Android應用程序,使用OpenCV作為本機部分,應采取以下步驟:

  1. 您可以使用環(huán)境變量來指定OpenCV包的位置,也可以在jni/Android.mk項目中硬編碼絕對或相對路徑。
  2. 該文件jni/Android.mk應使用通用規(guī)則此文件的當前應用程序被寫入。有關詳細信息,請參閱文件中的Android NDK歸檔的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)

   4、OpenCV Manager 可以使用多個變量來定制OpenCV,但是當您的應用程序通過OpenCV Manager API使用異步初始化時,您無需使用它們。

注意
這些變量應該在“include ... / OpenCV.mk”行之前設置
OPENCV_INSTALL_MODULES:=on

將必要的OpenCV動態(tài)庫復制到項目libs文件夾中,以便將它們包含在APK中。

OPENCV_CAMERA_MODULES:=off

跳過本機OpenCV相機相關的libs復制到項目libs文件夾。

OPENCV_LIB_TYPE:=STATIC

執(zhí)行與OpenCV的靜態(tài)鏈接。默認使用動態(tài)鏈接,項目JNI lib依賴于libopencv_java.so。

    5、該文件Application.mk應該存在并應包含行:

APP_STL:= gnustl_static
APP_CPPFLAGS:= -frtti -fexceptions

另外,像這樣的一行:

APP_ABI:= armeabi-v7a

應該指定應用程序目標平臺。

在某些情況下,根據(jù)OpenCV構(gòu)建應用程序JNI庫時,會發(fā)生鏈接錯誤(如“函數(shù)”cv :: toUtf16(std :: basic_string <...> ...未定義的引用“mbstowcs”)以下行Application.mk通常會修復它:

APP_PLATFORM:= android-9

   6、或者使用手動的 ndk-build調(diào)用或者設置Eclipse CDT Builder來構(gòu)建本地JNI庫,然后(重新)構(gòu)建Java部分并創(chuàng)建一個APK。

Hello OpenCV Sample

以下是引導您創(chuàng)建簡單的以OpenCV為中心的應用程序的過程的基本步驟。它將能夠訪問攝像機輸出,處理和顯示結(jié)果。

  • 打開Eclipse IDE,創(chuàng)建一個新的干凈工作區(qū),創(chuàng)建一個新的Android項目文件 - >新建 - > Android項目
  • 相應地設置名稱,目標,包和minSDKVersion。使用OpenCV4Android SDK構(gòu)建的最小SDK版本為11.最小設備API級別(應用程序清單)為8。
  • 允許Eclipse創(chuàng)建默認活動。讓我們將活動命名為HelloOpenCvActivity。
  • 選擇全屏布局的空白活動。讓我們命名布局HelloOpenCvLayout。
  • 將OpenCV庫項目導入到您的工作區(qū)。
  • 在項目屬性中引用OpenCV庫。

Android開發(fā)項目中使用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中設置應用程序主題以隱藏標題和系統(tǒng)按鈕。
<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);
}
  • 定義您的活動實現(xiàn)CvCameraViewListener2接口,并通過定義錯過的方法來修復與活動相關的錯誤。對于此活動,定義onCreate,onDestroy和onPause,并根據(jù)下面的代碼段來實現(xiàn)它們。通過添加必需的導入來修正錯誤
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應用程序都必須實現(xiàn)活動和查看。通過第一步,我們創(chuàng)建空白活動和默認視圖布局。最簡單的以OpenCV為中心的應用程序必須實現(xiàn)OpenCV初始化,創(chuàng)建自己的視圖來顯示來自相機的預覽,并實現(xiàn)CvCameraViewListener2接口從相機獲取幀并處理它。

首先,我們使用xml布局創(chuàng)建我們的應用程序視圖。我們的布局由org.opencv.android.JavaCameraView類中唯一的全屏組件組成。這個類在OpenCV庫中實現(xiàn)。它繼承自CameraBridgeViewBase,它擴展了SurfaceView并使用了標準的Android相機API。

創(chuàng)建布局后,我們需要實現(xiàn)Activity類。OpenCV初始化過程已經(jīng)在上面討論過了。在本例中,我們使用異步初始化。CvCameraViewListener接口的實現(xiàn)允許您在從相機抓取并在屏幕上渲染之前添加處理步驟。最重要的功能是onCameraFrame。它是回調(diào)函數(shù),它在從攝像機檢索幀時被調(diào)用。回調(diào)輸入是表示來自相機的幀的CvCameraViewFrame類的對象。

注意
不要保存或使用CvCameraViewFrame對象從onCameraFrame回調(diào)。這個對象沒有自己的狀態(tài),它的回調(diào)行為是不可預測的!

它具有rgba()和gray()方法,可以分別獲取幀為RGBA和一個通道灰度Mat。它期望onCameraFrame函數(shù)返回將在屏幕上繪制的RGBA幀。

以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號