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參數可以編輯。
按[Next]。Minimum SDK可以依sample選API 26。
按[Next]。
按[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:
按[Next]。
按[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],如下圖:
出現已經載入的opencv_java4_3,點選打勾。
按[OK]。
開啟build.gradle(app),dependencies{ }內自動加入
implementation project(path: ':opencv_java4_3'),如下圖:
步驟4:增加Native Libraries
1.複製.so檔,將\OpenCV-android-sdk\sdk\native\libs下所有檔案複製到\app\libs下。
2.指定jniLibs路徑,開啟app的build.gradle,增加:
sourceSets{
main {
jniLibs.srcDirs = ['libs']
}
}
(後續有完整程式碼)
步驟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); } } } |
留言列表