Android studio載入OpenCV 4.3 module

示範於新的Project中import OpenCV module,使用靜態初始化,把.so都包含在應用程序包,不使用異步初始化(程式包不含OpenCV apk,需下載安裝)。Android Studio版本 4.0、OpenCV 4.3。初學者可以先用OpenCV samples建立好的OpenCV環境,新增module進行練習,參考:Android studio新增OpenCV APP-初始化@KOEI的旅行 (本次會使用其中OpenCV初始化程式碼)。

前置工作:OpenCV SDK已經下載,sapmles也已經正確import,且正常執行,可參考:Android studio載入OpenCV範例@KOEI的旅行

 

Android studio載入OpenCV 4.3 module步驟

步驟1:新增Project

開啟Android Studio,點選File->New->New Project,Project Template選擇[Native C++] (如下圖),後續有cmake參數可以編輯。

import0_1.png

按[Next]。Minimum SDK可以依sample選API 26。

import0_2.png

按[Next]。

import0_3.png

按[Finish]即完成新增。

 

步驟2:Import OpenCV module

因為這版的Android Studio在import module時不能改名字,import OpenCV的目錄是\OpenCV-android-sdk\sdk\java,module名稱也會叫java,辨識度不佳,所以可以把上述目錄複製並改名,例如把java目錄內容複製到D:\OpenCV-android-sdk\java,並改名為opencv_java4_3,新的目錄變成D:\OpenCV-android-sdk\opencv_java4_3,import時改選這個目錄。

1.Import OpenCV java目錄

點選File->New->Import Module,目錄選擇\OpenCV-android-sdk\sdk\java,或是新建的D:\OpenCV-android-sdk\opencv_java4_3:

import1_2.png

按[Next]。

import1_3.png

按[Finish]。

2.修改OpenCV java的build.gradle

(1).把OpenCV從application改成 library才能import。

修改apply plugin: 'com.android.application' ,'application'改成'library'

(2).刪除applicationId,(否則有Library projects cannot set applicationId. applicationId is set to 'org.opencv' in default config.錯誤),刪除以下敘述:
defaultConfig {
    applicationId "org.opencv
}

修改後build.gradle(opencv_java4_3)如下:

apply plugin: 'com.android.library'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.2"

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.txt'
        }
    }
}

 

步驟3:dependencies加入OpenCV

點選File-> Project Structure ,進入Project Structure畫面,點選左邊Dependencies選項,Modules選app(新增的project module名稱),點[+](Add Dependency),出現增加的選項,選[3 Module Dependency],如下圖:

import1_6.png

出現已經載入的opencv_java4_3,點選打勾。

import1_7.png

按[OK]。

開啟build.gradle(app),dependencies{  }內自動加入

 implementation project(path: ':opencv_java4_3'),如下圖:

import1_8.png

 

步驟4:增加Native Libraries

1.複製.so檔,將\OpenCV-android-sdk\sdk\native\libs下所有檔案複製到\app\libs下。

2.指定jniLibs路徑,開啟app的build.gradle,增加:

    sourceSets{
        main {
            jniLibs.srcDirs = ['libs']
        }
    }

import1_9.png

(後續有完整程式碼)

 

步驟5:複製OpenCV初始化程式

修改MainActivity.java,複製onResume程式碼,呼叫OpenCVLoader.initDebug(),判斷本機是否包含OpenCV;複製BaseLoaderCallback程式。

(後續有完整程式碼MainActivity.java)

 

步驟6:執行OpenCV初始化

如果APP順利顯示Hello from c++,表示載入OpenCV成功。

如果畫面出現:

Package not found
OpenCV Manager package was not found! Try to install it  

log顯示出現:

D/Sample-test::Activity: Internal OpenCV library not found. Using OpenCV Manager for initialization

表示靜態初始化沒成功,在Run log會顯示

E/OpenCV/StaticHelper: OpenCV error: Cannot load info library for OpenCV
W/System.err: java.lang.UnsatisfiedLinkError: dlopen failed: library "libc++_shared.so" not found

解決方式:在build.gradle(app)的cmake增加

arguments "-DANDROID_STL=c++_shared"

修改後完整build.gradle(app)內容如下:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 26
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
                arguments "-DANDROID_STL=c++_shared"
            }
        }
    }

    sourceSets{
        main{
            jniLibs.srcDirs = ['libs']
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    implementation project(path: ':opencv_java4_3')
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'

}

執行後log顯示
D/Sample-test::Activity: OpenCV library found inside package. Using it!

表示載入成功,開始OpenCV的程式了。

(也有其他作法把libc++_shared.so複製到需要的libopencv_java4.so目錄下,但試過沒成功,可能還要其他設定。)

 

完整MainActivity.java (Hello from c++):

package com.example.myapplication;

import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;

public class MainActivity extends AppCompatActivity {
    private static final String  TAG = "Sample-test::Activity";

    // Used to load the 'native-lib' library on application startup.
    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Example of a call to a native method
        TextView tv = findViewById(R.id.sample_text);
        tv.setText(stringFromJNI());
    }

    /**
     * A native method that is implemented by the 'native-lib' native library,
     * which is packaged with this application.
     */
    public native String stringFromJNI();

    private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                    Log.i(TAG, "OpenCV loaded successfully");
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };

    @Override
    public void onResume()
    {
        super.onResume();
        if (!OpenCVLoader.initDebug()) {
            Log.d(TAG, "Internal OpenCV library not found. Using OpenCV Manager for initialization");
            OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_0_0, this, mLoaderCallback);
        } else {
            Log.d(TAG, "OpenCV library found inside package. Using it!");
            mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
        }
    }
}

 

arrow
arrow
    創作者介紹
    創作者 KOEI 的頭像
    KOEI

    KOEI的旅行

    KOEI 發表在 痞客邦 留言(1) 人氣()