一区二区三区三上|欧美在线视频五区|国产午夜无码在线观看视频|亚洲国产裸体网站|无码成年人影视|亚洲AV亚洲AV|成人开心激情五月|欧美性爱内射视频|超碰人人干人人上|一区二区无码三区亚洲人区久久精品

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評(píng)論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫(xiě)文章/發(fā)帖/加入社區(qū)
會(huì)員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識(shí)你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

運(yùn)用JNI連結(jié)OpenCV開(kāi)發(fā)C++并打包成aar lib的使用教學(xué)

新機(jī)器視覺(jué) ? 來(lái)源:深度學(xué)習(xí)與計(jì)算機(jī)視覺(jué) ? 作者:深度學(xué)習(xí)與計(jì)算機(jī) ? 2022-08-15 09:24 ? 次閱讀
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

動(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 即可。540546ce-1c2c-11ed-ba43-dac502259ad0.png取名叫MyApp,方便之后模擬使用這個(gè)lib 的人。54271fce-1c2c-11ed-ba43-dac502259ad0.png由于我們最終目的是要做一個(gè) aar lib 。所以 myapp 用來(lái)當(dāng)作 application 使用,另外,再新增一個(gè)Module 來(lái)作為 C++ lib 開(kāi)發(fā)。點(diǎn)選 [Files]>[New]>[New Module…] 新增 MyOpenCv。543b9198-1c2c-11ed-ba43-dac502259ad0.png這時(shí)的目錄結(jié)構(gòu)如下,除了 app 以外,多了MyOpenCv 這個(gè)Module,有CMakeLists.txt, myopencv.cpp, NativeLib三個(gè)檔案。5450c2e8-1c2c-11ed-ba43-dac502259ad0.png此時(shí),到 app 的 build.gradle 新增剛剛的module 作為依賴并執(zhí)行g(shù)radle sync。5469d558-1c2c-11ed-ba43-dac502259ad0.pngsync 后,可以到 app 的MainActivity.java 測(cè)試是不是可以抓到 JNI 的信息。5485aa58-1c2c-11ed-ba43-dac502259ad0.png54b3c38e-1c2c-11ed-ba43-dac502259ad0.png這階段就完成了從Android 呼叫C++ Lib部分。備注1: 這邊 CMakeLists.txt 能與Android 連接是通過(guò)build.gradle 里的這段:

	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/54d396c8-1c2c-11ed-ba43-dac502259ad0.png接著在CMakeLists.txt 加入OpenCV 依賴并執(zhí)行Gradle Sync。其中 jnigraphics-lib 是等會(huì)將圖片格式由Android Bitmap 轉(zhuǎn)成OpenCV Mat 格式時(shí)會(huì)用到的。

	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 套件。54f2cf5c-1c2c-11ed-ba43-dac502259ad0.png檢視警告頁(yè)面提示為:無(wú)法找到abi binary,位置在OpenCVConfig.cmake:4755032a28-1c2c-11ed-ba43-dac502259ad0.png然后…經(jīng)過(guò)我漫長(zhǎng)的尋找…不斷的在cmake file 里用message() 確認(rèn)各個(gè)變數(shù),終于發(fā)現(xiàn)在OpenCVConfig.cmake 這個(gè)檔案里的第39行中ANDROID_NDK_ABI_NAME 的值都是空的!理論上它應(yīng)該會(huì)是:[arm64-v8a, armeabi-v7a, x86, x86_64] ,各代表在不同環(huán)境的CPU架構(gòu)。552f5634-1c2c-11ed-ba43-dac502259ad0.pngOpenCVConfig.cmake嘗試注解掉原本的ANDROID_NDK_ABI_NAME 后,替換成 ANDROID_ABI 就可以成功的sync。5544a246-1c2c-11ed-ba43-dac502259ad0.png等 sync 完成后,就可以在myopencv.cpp 檔案里引用OpenCV 而不會(huì)出錯(cuò)。556c8de2-1c2c-11ed-ba43-dac502259ad0.png備注:如果你自己的電腦本身有安裝OpenCV ,不使用官網(wǎng)下載的OpenCV_DIR ,它可能會(huì)自己跑去找系統(tǒng)的版本(/usr/local/lib/cmake/opencv4),而發(fā)生錯(cuò)誤。我自己有發(fā)生set(OpenCV_DIR path) 路徑打錯(cuò),跑去抓/usr/local 底下的版本,然后不斷出現(xiàn):

	C/C++:CMakeFiles/cvmodule.dir/cvmodule.cpp.o(.data+0x0):error:undefinedreferenceto'typeinfoforcv::Exception' 的錯(cuò)誤。

OpenCV bash 開(kāi)發(fā)

  1. 開(kāi)發(fā)圖片轉(zhuǎn)灰度功能
新增一個(gè)將圖片轉(zhuǎn)成灰度的功能測(cè)試,這邊要注意的是在JNI 使用上,必須定義好function 的signature,像名稱要和java 的package name 對(duì)應(yīng)。

	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)成灰色。557d1db0-1c2c-11ed-ba43-dac502259ad0.png

	@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); } 558f71a4-1c2c-11ed-ba43-dac502259ad0.png
  1. 開(kāi)發(fā)讀取圖片寬高功能
比如說(shuō)今天Android Team 有個(gè)需求是傳一張圖片,我們分析圖片寬高等資訊,而且希望他們可以直接拿到 Java Class。我們先在Module 里新增一個(gè)DTO 叫ImageInfo。

	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,"","(II)V"); returnenv->NewObject(cls,constructor,width,height); } 完成后,再回到 app 里實(shí)際測(cè)試。

	//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文件夾)559f4566-1c2c-11ed-ba43-dac502259ad0.png

打包成 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 做示范。55c3758a-1c2c-11ed-ba43-dac502259ad0.png設(shè)成release 之后,再去[Build]>[Rebuild Project]讓工程建構(gòu)一下,完成后會(huì)在build 文件夾的outputs 找到我們要的aar。55cf6372-1c2c-11ed-ba43-dac502259ad0.png打開(kāi)MyOpenCv-release.aar 可以看到在jni 里面存放各個(gè)不同架構(gòu)的.so,代表正常。55f10590-1c2c-11ed-ba43-dac502259ad0.png我們開(kāi)啟令一個(gè)Android Project 叫AnotherApp ,并把MyOpenCv-release.aar 放入app/libs 里。560910f4-1c2c-11ed-ba43-dac502259ad0.png然后在AnotherApp 的build.gradle 加入依賴。5624df78-1c2c-11ed-ba43-dac502259ad0.png然后回到AnotherApp 的MainActivity我們加入這四行,測(cè)試自己撰寫(xiě)的aar lib 能不能成功使用。5634d91e-1c2c-11ed-ba43-dac502259ad0.png執(zhí)行結(jié)果是程序有抓到圖片在畫(huà)面上的寬高。565f587e-1c2c-11ed-ba43-dac502259ad0.png以上就完成了運(yùn)用JNI 連結(jié)OpenCV 開(kāi)發(fā)C++,并打包成aar lib 的使用教學(xué)。

代碼:

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_lib

Ref

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

審核編輯:湯梓紅


聲明:本文內(nèi)容及配圖由入駐作者撰寫(xiě)或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場(chǎng)。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問(wèn)題,請(qǐng)聯(lián)系本站處理。 舉報(bào)投訴
  • C++
    C++
    +關(guān)注

    關(guān)注

    22

    文章

    2119

    瀏覽量

    75259
  • OpenCV
    +關(guān)注

    關(guān)注

    32

    文章

    642

    瀏覽量

    42858
  • JNI
    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)注明出處。

收藏 人收藏
加入交流群
微信小助手二維碼

掃碼添加小助手

加入工程師交流群

    評(píng)論

    相關(guān)推薦
    熱點(diǎn)推薦

    【實(shí)用開(kāi)發(fā)工具】將BAT腳本打包成exe可執(zhí)行文件

    【實(shí)用開(kāi)發(fā)工具】將BAT腳本打包成exe可執(zhí)行文件
    的頭像 發(fā)表于 08-21 19:51 ?2.7w次閱讀
    【實(shí)用<b class='flag-5'>開(kāi)發(fā)</b>工具】將BAT腳本<b class='flag-5'>打包成</b>exe可執(zhí)行文件

    lib封裝庫(kù)如何反匯編成C語(yǔ)言

    小弟想請(qǐng)教論壇上的大神們:用C語(yǔ)言編寫(xiě)的程序打包成lib封裝庫(kù)如何反匯編成C語(yǔ)言??
    發(fā)表于 06-12 20:52

    請(qǐng)問(wèn)C++如何運(yùn)用到具體的工程中?

    學(xué)了很多C語(yǔ)言,現(xiàn)在想學(xué)習(xí)一下C++,但是現(xiàn)在遇到一個(gè)問(wèn)題,就是不知道C++怎么運(yùn)用到具體的工程中。學(xué)習(xí)C語(yǔ)言可以在單片機(jī)和Linux上
    發(fā)表于 03-24 04:35

    在鴻蒙的Module中使用了JNI無(wú)法調(diào)試代碼中的C++是為什么

    各位大佬,請(qǐng)教個(gè)問(wèn)題。目前在做JNI開(kāi)發(fā)中,在鴻蒙的Module中使用了JNI,如果編譯使用正常,但是調(diào)試時(shí)無(wú)法在C++中調(diào)試代碼中的C++
    發(fā)表于 04-24 11:11

    OpenCV C++程序編譯與演示

    1、在JetsonNano上編譯OpenCV源碼與OpenCV C++ YOLOv5程序演示  編譯OpenCV最新4.5.x版本  Jetson Nano自帶的
    發(fā)表于 11-10 16:42

    一文簡(jiǎn)析JNI層使用C/C++需要輸出Log

    Platform: RK3399OS: Android 7.1Kernel: v4.4.83JNI層使用C/C++需要輸出Log.如果不要TAG,那么只要如下使用就可以:#include &
    發(fā)表于 11-22 17:59

    能請(qǐng)教一下官方的pyOCD是怎么打包成獨(dú)立exe的嗎?

    能請(qǐng)教一下官方的 pyOCD 是怎么打包成獨(dú)立 exe 的?最近我也想打包一個(gè) pyOCD,但是用 pyinstaller 打包后,運(yùn)行提示OSError: cannot load library
    發(fā)表于 12-05 11:33

    C++課程設(shè)計(jì)教學(xué)大鋼

    C++課程設(shè)計(jì)教學(xué)大鋼 課程名稱:C++課程設(shè)計(jì)英文名稱:Course design of C++ Programming面向?qū)I(yè):對(duì)計(jì)算機(jī)要求較高的理工科專業(yè)課程總學(xué)時(shí):___ 4
    發(fā)表于 06-25 23:28 ?9次下載

    程序設(shè)計(jì)及C++語(yǔ)言課程設(shè)計(jì)教學(xué)大鋼

    程序設(shè)計(jì)及C++語(yǔ)言課程設(shè)計(jì)教學(xué)大鋼:程序設(shè)計(jì)及C++語(yǔ)言》課程設(shè)計(jì)教學(xué)大鋼(課程設(shè)計(jì)類) 課程設(shè)計(jì) 名稱:C++語(yǔ)言課程設(shè)計(jì)英文名稱:C
    發(fā)表于 06-25 23:29 ?15次下載

    OpenCV2.3的C++速查表免費(fèi)下載

    本文檔的主要內(nèi)容詳細(xì)介紹的是OpenCV2.3的C++速查表免費(fèi)下載。
    發(fā)表于 11-06 17:48 ?4次下載

    RSA算法的JNI封裝步驟

    要求較高的算法往往是基于C/C++語(yǔ)言(與硬件關(guān)聯(lián)性更強(qiáng))實(shí)現(xiàn)的。如果應(yīng)用程序需要基于JAVA編程實(shí)現(xiàn)時(shí),這就會(huì)有一些矛盾。此時(shí),通過(guò)JNI技術(shù),Java開(kāi)發(fā)者可以在不了解算法內(nèi)容的情
    的頭像 發(fā)表于 06-04 17:45 ?2453次閱讀
    RSA算法的<b class='flag-5'>JNI</b>封裝步驟

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

    本文檔的主要內(nèi)容詳細(xì)介紹的是如何使用Borland C++ Builder6.0來(lái)開(kāi)發(fā)OpenCV的程序。
    發(fā)表于 05-26 17:32 ?14次下載
    如何使用Borland <b class='flag-5'>C++</b> Builder6.0來(lái)<b class='flag-5'>開(kāi)發(fā)</b><b class='flag-5'>OpenCV</b>的程序

    【Python】如何將Python腳本打包成exe可執(zhí)行文件

    【Python實(shí)用技巧】如何將Python腳本打包成exe可執(zhí)行文件?
    的頭像 發(fā)表于 08-18 12:40 ?1.9w次閱讀
    【Python】如何將Python腳本<b class='flag-5'>打包成</b>exe可執(zhí)行文件

    基于QT5+OpenCV+OpenVINO C++的應(yīng)用打包過(guò)程

    我用QT C++寫(xiě)了一個(gè)YOLOv5模型推理演示應(yīng)用。
    的頭像 發(fā)表于 01-26 10:17 ?2136次閱讀
    基于QT5+<b class='flag-5'>OpenCV</b>+OpenVINO <b class='flag-5'>C++</b>的應(yīng)用<b class='flag-5'>打包</b>過(guò)程

    OpenCV圖像識(shí)別C++代碼

    的頭文件 在您的C++代碼中,包含以下必要的頭文件: # include # include # include # include # include # include # include 讀取圖像
    的頭像 發(fā)表于 07-16 10:42 ?4608次閱讀