先說下題外話哈,最近做了個領取電商平臺優惠券的小程序,掃碼支持下哈~
image
最近看了一些opencv的相關內容,這里做一下記錄以及學習中的體會,和大家分享一下,本人在學習的時候也是網上查閱很多人的博客。
現在都是開源時代,opencv也是一個開源庫,也有官網和社區,所以簡介什么的大家去官網看看,了解什么是opencv,用來干什么的,這里就不羅嗦了。
1、下載
可以根據自己的工作平臺下載對應的資源,本人實在android的領域下使用opencv,所以下載的是3.4.5 Android pack,后面的內容也是針對opencv在android開發中的使用。
2、sdk結構
下載解壓后的文件結構如下
- apk:這個包下面是opencv-manager安裝包,具體作用后面在細說。
- samples:是opencv官方提供的幾個demo工程,有工程源代碼,也有打包好的apk。
- sdk:這個是重點,以后開發的時候也是用的這里面的東西。
- etc:識別相關的級聯分類器之類的,目前我也不太懂,前期學習也用不到。
- java:這是opencv官方提供的一個opencv的android庫工程,提供了完整的opencv能力,因為opencv底層是用c/c++寫的,但是現在編程語言很多,java、python等等,所以官方就針對不同的語言平臺,對底層庫進行了二次封裝,使用的時候將該該工程直接作為庫導入即可,后面會細說。
- native:一些native層的庫
- 3rdparty:第三方的一些庫
- jni:一些cmake編譯腳本和動態庫的頭文件
- libs:官方根據不同平臺架構打好的.so動態庫,提供完整的opencv能力,體積稍大,單個架構對應的.so文件體積在10M以上
- staticlibs:將不同的功能分別做成.a靜態庫,可以根據使用到的opencv能力,選擇加載相應的.a靜態庫,有利于降低應用體積。
3、開發機制
opencv底層是c/c++寫的,語言門檻高,另外涉及的數學、圖形學等知識也加大了學習難度,所以官方針對不同水平和應用方向的人員提供了不同的開發方式,以造福廣大的opencv能力需要者。
1、要不要在項目中配置sdk中native庫?
在使用opencv能力之前,需要加載opencv提供的native庫,opencv提供了兩種方式:
- 從應用本地包下面加載,要求相關的native層的庫、頭文件等要拷貝到項目工程中,并配置好,應用運行時就會按照配置從應用本地進行加載。
- 設備上提前安裝 opencv-manager,是一個apk安裝包,以aidl的方式向其他應用提供opencv能力,所以開發應用時就不需要在拷貝native庫什么的到項目中,因為app運行時可以通過aidl方式,從opencv-manager中進行加載。
為什么opencv要提供這兩種方式呢?
原因就在于上面說過opencv的native庫文件體積比較大。
如果是從本地包進行加載,設備上安裝的應用很多都使用opencv的話,每個應用下都要拷貝一份native庫文件,浪費存儲空間,另外項目中配置native庫也相對繁瑣。
雖然設備上提前安裝 opencv-manager的方式節省了存儲空間,但是一個硬傷就是不能保證用戶設備上實現安裝了opencv-manager,再說了,用戶也不會為了你的一個app而提前安裝另外一個app,用戶才不會聽你的。
所以,自己學習或者開發demo的時候可以用提前安裝 opencv-manager的方式,省去了拷貝、配置native庫的操作,也節省了手機空間。但是如果開發正式的app還是老老實實的從本地包加載為好。
2、涉不涉及ndk開發?
android開發目前來說java仍是主流,kotlin雖然越來越流行,但是對java是全兼容的。 opencv底層是c/c++實現的。 所以android中使用opencv能力就需要解決兩種語言通信的問題,使用的方案當然是jni啦,opencvsdk的java工程對jni調用opencv方法進行了封裝,開發時直接調用封裝好的java方法即可實現opencv能力的調用,很爽吧,不用和c/c++打交道。
但是畢竟opencv底層是c/c++實現的,想要100%使用opencv的能力,或者sdk的java庫中提供的方法不能滿足需求,還是需要自己使用c/c++去實現一部分功能,自行封裝成jni方法使用。再說了現在都是團隊開發,可以有專門的小伙伴實現底層的工作,對吧,這就需要拷貝、配置相關的native庫,使用ndk進行開發。
當然了,更厲害的大神可以下載源碼進行修改,自行編譯,不僅可以得到最新的sdk,而且能夠根據需要,自行實現底層相關算法之類的。
這里對不同的開發機制的適用場景進行簡單的總結:
- java庫+opencv-manager.apk:適用于個人學習或者做demo,在設備上事先安裝opencv-manager.apk,然后項目中導入java庫工程,即可進行后續開發。
- java庫+native庫:對opencv能力沒有特殊要求的情況下,開發線上應用。
- java庫+native庫+自行封裝實現的jni方法:開發線上應用,但是java庫提供的opencv能力不能滿足業務需求時使用這種方式。
4、開發實戰
經過上面的討論,對android下opencv的開發機制有了大概了解,下面的分別對幾種開發方式進行簡單的實現。
1、java庫+opencv-manager.apk
準備
需要準備的東西是sdk的java庫工程以及設備平臺對應的opencv-manager.apk
配置
- 在設備上安裝opencv-manager.apk
- 在android studio中新建一個工程,已經有的話直接打開
- 導入sdk的java庫工程:
File-New-Import module
,定位到java庫工程,導入后庫工程的module name 為openCVLibrary343 - 配置主module依賴openCVLibrary343:在主modlue的guild.gradle文件的dependencies節點下添加
implementation project(':openCVLibrary343')
,然后同步代碼即可。
開發
在 Activity 的 onResume 方法中初始化opencv
//使用OpenCV Engine service,需要運行設備事先安裝OpenCV Manager
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, this, new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
if (status == LoaderCallbackInterface.SUCCESS) {
Log.d(TAG, "onManagerConnected: success");
} else {
super.onManagerConnected(status);
}
}
});
對圖片進行均值模糊
//本地加載圖片
Bitmap originImg = BitmapFactory.decodeFile("filePath");
//初始化Mat
Mat src = new Mat(originImg.getHeight(), originImg.getWidth(), CvType.CV_8UC4);
//bitmap轉mat
Utils.bitmapToMat(originImg, src);
//均值模糊
Imgproc.blur(src, src, new Size(3, 3));
//初始化處理后bitmap
Bitmap processedImg = Bitmap.createBitmap(src.cols(), src.rows(), Bitmap.Config.ARGB_8888);
//mat轉bitmap
Utils.matToBitmap(src, processedImg);
2、java庫+native庫
和上種方式的區別在于:
- 不需要事先安裝opencv-manager.apk
- 需要在項目中配置native庫
準備
需要準備的東西是sdk的java庫工程、native庫(sdk-native-libs)
配置
- 導入java庫工程,并配置依賴,具體步驟在【java庫+opencv-manager.apk】開發方式中有描述
- 將libs文件夾復制拷貝到項目工程的src-main-jniLibs路徑下,如果jniLis文件夾不存在就自己新建一個
- 打開module的build.gradle文件,在 android 節點下添加如下代碼,然后同步代碼即可
sourceSets {
main {
jniLibs.srcDirs = ['src/main/jniLibs/libs']
}
}
開發
和【java庫+opencv-manager.apk】開發方式初始化opencv的時候有區別,其他都一樣。
在 Activity 的 onResume 方法中初始化opencv
//使用應用本地native庫
OpenCVLoader.initDebug();
3、java庫+native庫+自行封裝實現的jni方法
這種方式是在【java庫+native庫】開發方式的基礎上使用ndk進行jni開發。
準備
需要準備的東西是sdk的java庫工程、native庫(sdk-native-libs)、native庫頭文件(sdk-native-jni-include)
配置
- 參考博客【音視頻開發01–AS3.x NDK開發環境搭建】建立支持ndk開發的項目。
- 完成【java庫+native庫】開發方式中的相關配置。
- 將native庫頭文件(sdk-native-jni-include)拷貝到src-main-cpp目錄下(如果沒有該目錄,請先按照【音視頻開發01–AS3.x NDK開發環境搭建】的過程進行操作)
- 編輯 CMakeLists.txt 文件內容(如果沒有該文件,請先按照【音視頻開發01–AS3.x NDK開發環境搭建】的過程進行操作)
- 配置比較繁瑣,如果出現問題,請積極搜索,學習android studio cmake ndk開發的相關知識。
cmake_minimum_required(VERSION 3.4.1)
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include)
add_library(libopencv_java3 SHARED IMPORTED)
set_target_properties(libopencv_java3 PROPERTIES IMPORTED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/libs/${ANDROID_ABI}/libopencv_java3.so)
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
target_link_libraries( # Specifies the target library.
native-lib libopencv_java3
# Links the target library to the log library
# included in the NDK.
${log-lib} )
開發
看demo吧,就是jni開發那一套。
總結
android中使用opencv進行開發時,針對不同的開發和應用場景選擇開發方式,總的來說涉及的東西挺多的,android知識、ndk/jni知識、c/c++知識、opencv知識、數學知識等。
學習的時候以android 開發為基礎,通過本文搭建起開發框架,在寫demo的過程中學習opencv api和相關的理論知識,同時也學習了ndk/jni和c/c++。