動(dòng)機(jī)
- 本身是作影像視覺(jué)相關(guān)的工作,多數(shù)時(shí)候都使用 Python 作為開(kāi)發(fā)語(yǔ)言,但OpenCV 本身是C++開(kāi)發(fā),學(xué) C++ 應(yīng)該有幫助。
- 公司有 Android/iOS Team ,有些功能需要與他們整合,多了解對(duì)方領(lǐng)域可以減少溝通成本。
- 網(wǎng)絡(luò)上有關(guān) OpenCV 與 Android Studio 整合的教學(xué)零散文章,這次整合成功后,把這些碎片化資訊整理起來(lái)記錄,避免之后有同樣需求時(shí)又辛苦一次,這次整合采了太多坑,如果不做個(gè)記錄,三個(gè)月后就會(huì)忘了。
環(huán)境
- Android Studio Chipmunk | 2021.2.1 Patch 1 (Ubuntu 環(huán)境)
- JNI 有 cmake 和ndk-build兩種方法,我是用Cmake (版本3.22.1 )如果你參考的教學(xué)有用到 Android.mk 或Application.mk ,那這篇有關(guān) build 的方式會(huì)很不一樣。
- OpenCV 4.5.5 / 4.6.0
Android Studio 連結(jié) JNI
開(kāi)啟新工程,使用Base Activity 即可。






externalNativeBuild{ cmake{ path"src/main/cpp/CMakeLists.txt" version"3.18.1" } } 備注2: MyOpenCv Module 和app 可以相連是通過(guò)settings.gradle 后兩行的include。
pluginManagement{ repositories{ gradlePluginPortal() google() mavenCentral() } } dependencyResolutionManagement{ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories{ google() mavenCentral() } } rootProject.name="MyApp" include':app' include':MyOpenCv'
Cmake 與OpenCV 依賴
先至 OpenCV 官網(wǎng)(https://opencv.org/releases/)下載Andoird 版本并解壓縮到想要的文件夾,這邊示例是在/home/user/Documents/
cmake_minimum_required(VERSION3.18.1) set(OpenCV_DIR"/home/jason9075/Documents/OpenCV-android-sdk/sdk/native/jni") find_package(OpenCVREQUIRED) project("myopencv") add_library(myopencv SHARED myopencv.cpp) include_directories(${OpenCV_INCLUDE_DIRS}) find_library(log-lib log) #ForAndroidBitverttocv::Mat find_library(jnigraphics-libjnigraphics) target_link_libraries(myopencv ${OpenCV_LIBS} ${jnigraphics-lib}#ForAndroidBitmapCoverttocv::Mat ${log-lib}) 這時(shí)你會(huì)發(fā)現(xiàn)Sync 失敗, 問(wèn)題出在CMakeLists.txt 第五行沒(méi)有抓到OpenCV 套件。





C/C++:CMakeFiles/cvmodule.dir/cvmodule.cpp.o(.data+0x0):error:undefinedreferenceto'typeinfoforcv::Exception' 的錯(cuò)誤。
OpenCV bash 開(kāi)發(fā)
- 開(kāi)發(fā)圖片轉(zhuǎn)灰度功能
extern"C"JNIEXPORTvoidJNICALL Java_com_jason9075_myopencv_NativeLib_toGrey( JNIEnv*env, jobject, jobjectbitmapIn, jobjectbitmapOut){ Matsrc,greyOut; bitmapToMat(env,bitmapIn,src,false); cvtColor(src,greyOut,CV_BGR2GRAY); matToBitmap(env,greyOut,bitmapOut,false); } 然后在NativeLib.java 里要宣告與C++對(duì)應(yīng)的function。
publicclassNativeLib{ static{ System.loadLibrary("myopencv"); } publicnativeStringstringFromJNI(); publicnativevoidtoGrey(BitmapbitmapIn,BitmapbitmapOut); } 為了測(cè)試我們到應(yīng)用程式app文件夾,把Android綠色機(jī)器人圖片放到drawable 文件夾,然后在MainActivity 轉(zhuǎn)成灰色。

@Override protectedvoidonCreate(BundlesavedInstanceState){ super.onCreate(savedInstanceState); binding=ActivityMainBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); NavControllernavController=Navigation.findNavController(this,R.id.nav_host_fragment_content_main); appBarConfiguration=newAppBarConfiguration.Builder(navController.getGraph()).build(); NavigationUI.setupActionBarWithNavController(this,navController,appBarConfiguration); ImageViewiv=findViewById(R.id.imageView); binding.fab.setOnClickListener(newView.OnClickListener(){ @Override publicvoidonClick(Viewview){ Snackbar.make(view,"Replacewithyourownaction",Snackbar.LENGTH_LONG) .setAction("Action",null).show(); } }); //TestHelloWorldFromMyOpenCv NativeLibcv=newNativeLib(); System.out.println(cv.stringFromJNI()); Bitmapimage=BitmapFactory.decodeResource(getResources(),R.drawable.android); cv.toGrey(image,image); iv.setImageBitmap(image); }

- 開(kāi)發(fā)讀取圖片寬高功能
packagecom.jason9075.myopencv; publicclassImageInfo{ privatefinalintwidth; privatefinalintheight; publicImageInfo(intwidth,intheight){ this.width=width; this.height=height; } publicintgetWidth(){ returnwidth; } publicintgetHeight(){ returnheight; } @Override publicStringtoString(){ return"ImageInfo{"+ "width="+width+ ",height="+height+ '}'; } } 在 NativeLib.java 宣告相對(duì)應(yīng)的 function getInfo()
packagecom.jason9075.myopencv; importandroid.graphics.Bitmap; publicclassNativeLib{ static{ System.loadLibrary("myopencv"); } publicnativeStringstringFromJNI(); publicnativevoidtoGrey(BitmapbitmapIn,BitmapbitmapOut); publicnativeImageInfogetInfo(Bitmapbitmap); } 然后在myopencv.cpp 新增C++ 實(shí)做方式。須注意的一點(diǎn)是,因?yàn)槲覀冏罱K要回傳 Java Object,所以在C++這邊要定義clsPath ,要找你預(yù)期回傳的 Java Class 長(zhǎng)的怎么樣,還有這個(gè)Class 的Constructor 需要什么樣的signature (這邊 width 和 height 都是 Int 所以是(II)V)。
extern"C" JNIEXPORTjobjectJNICALL Java_com_jason9075_myopencv_NativeLib_getInfo(JNIEnv*env,jobjectthiz,jobjectbitmap){ Matsrc; bitmapToMat(env,bitmap,src,false); intwidth=src.cols; intheight=src.rows; //returnjavaobject constchar*clsPath="com/jason9075/myopencv/ImageInfo"; jclasscls=env->FindClass(clsPath); jmethodIDconstructor=env->GetMethodID(cls,"
//TestHelloWorldFromMyOpenCv NativeLibcv=newNativeLib(); System.out.println(cv.stringFromJNI()); Bitmapimage=BitmapFactory.decodeResource(getResources(),R.drawable.android); cv.toGrey(image,image); iv.setImageBitmap(image); System.out.println(">>>"+cv.getInfo(image)); 我們可以成功讀取到寬高分別為2688 和3197。(這邊和原圖寬高不同的原因是Android 的Drawable 會(huì)自動(dòng)縮放,若想測(cè)試原圖可以改放Asset文件夾)

打包成 aar 給其他工程使用
上面的工程主要有兩個(gè)部分,一個(gè)是 app 擁有Activity 來(lái)模擬使用這個(gè)lib的情況,令一個(gè)部分是 MyOpenCv 這個(gè)module 為實(shí)際lib 的內(nèi)容,這是我們接下來(lái)要介紹的,如何將這個(gè)module 轉(zhuǎn)成aar。首先,我們先點(diǎn)擊 [Build]>[Select Build Varient] 開(kāi)啟選單,再生成 aar 時(shí)可以選擇 debug 或是 release 來(lái)發(fā)布,這邊我選用release 做示范。






代碼:
MyApp: https://github.com/jason9075/Android_with_OpenCV_Module溫馨提醒:使用時(shí)module 的CMakeLists.txt 請(qǐng)將OpenCV_DIR換成自己的sdk路徑。AnotherApp: https://github.com/jason9075/Android_use_OpenCV_AAR_libRef
https://developer.android.com/studio/projects/configure-cmakehttps://github.com/ValYouW/AndroidOpenCVDemohttps://stackoverflow.com/questions/9433257/how-to-specify-array-of-class-in-getmethodid-method-signature-parameterhttps://stackoverflow.com/questions/22300848/return-object-from-java-native-methodhttps://stackoverflow.com/questions/51107185/how-to-create-new-android-aar-in-android-studio審核編輯:湯梓紅
-
C++
+關(guān)注
關(guān)注
22文章
2119瀏覽量
75259 -
OpenCV
+關(guān)注
關(guān)注
32文章
642瀏覽量
42858 -
JNI
+關(guān)注
關(guān)注
0文章
8瀏覽量
8024
原文標(biāo)題:?如何將 OpenCV 整合 Android JNI 開(kāi)發(fā) C++ 代碼并打包成 aar lib 給其他工程使用
文章出處:【微信號(hào):vision263com,微信公眾號(hào):新機(jī)器視覺(jué)】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
lib封裝庫(kù)如何反匯編成C語(yǔ)言
請(qǐng)問(wèn)C++如何運(yùn)用到具體的工程中?
在鴻蒙的Module中使用了JNI無(wú)法調(diào)試代碼中的C++是為什么
OpenCV C++程序編譯與演示
一文簡(jiǎn)析JNI層使用C/C++需要輸出Log
能請(qǐng)教一下官方的pyOCD是怎么打包成獨(dú)立exe的嗎?
C++課程設(shè)計(jì)教學(xué)大鋼
程序設(shè)計(jì)及C++語(yǔ)言課程設(shè)計(jì)教學(xué)大鋼
OpenCV2.3的C++速查表免費(fèi)下載
RSA算法的JNI封裝步驟

如何使用Borland C++ Builder6.0來(lái)開(kāi)發(fā)OpenCV的程序

評(píng)論