本文中,我們主要爲大家介紹以下內容:
- OpenCV4Android SDK下載
- Android項目中導入OpenCV Module
- Android項目中剔除OpenCVManager apk的依賴
- 使用OpenCV完成圖像灰度化
OpenCV
是一個基於BSD
許可(開源)發行的跨平臺計算機視覺庫,可以運行在Linux
、Windows
、Android
和Mac OS
操作系統上。它輕量級而且高效——由一系列 C
函數和少量 C++
類構成,同時提供了Python
、Ruby
、MATLAB
等語言的接口,實現了圖像處理和計算機視覺方面的很多通用算法(更多介紹參見百度百科)
簡單來說,OpenCV
就是一個用於圖像處理及計算機視覺的跨平臺開源算法庫,我們可以利用OpenCV
內部提供的算法進行圖像處理應用開發,或者從事計算機視覺相關方向的研發工作。
那麼如何在Android
平臺使用OpenCV
呢?我們一起來看下。
OpenCV4Android SDK
和大多數開源庫一樣,針對不同的平臺打包不同的SDK
依賴庫,OpenCV
也是一樣的。我們可以在其官網下載OpenCV4Android SDK
,這是OpenCV
Android
平臺的依賴庫,其內部包含OpenCV
在Android
平臺的demo
項目代碼以及OpenCV
源碼文件。
首先打開OpenCV
官網:OpenCV官網(https://opencv.org/)
進入官網後點擊右上角的release
菜單,如下圖:
隨後在這個頁面我們就可以看到當前OpenCV
發佈過的所有版本,每個版本內部都會列舉各個平臺的依賴包,我們選擇最新版本4.2.0
中的Android
下載4.2.0版本對應的Android
平臺依賴包,如下圖:
下載完成後解壓,我們可以得到如下文件目錄:
其中各目錄包含的主要內容如下:
- sdk:
OpenCV
源碼目錄,該目錄包含OpenCV java module
,OpenCV libs
文件以及OpenCV C++
源碼文件 - samples:
OpenCV Android
示例項目目錄
導入OpenCV4Android SDK
在Android Studio
內新建Android
項目(PS:記得勾選C++支持),構建成功後,切換到Project
視圖,如下所示:
隨後在項目名稱(圖中OpenCV01處)右鍵依次選擇new->Module,選擇完成後彈出下圖界面:
向下滾動選擇import eclipse adt project
,隨後點擊next
,在接下來的窗口中選在OpenCV_SDK_PATH/sdk/java
,命名導入的Module
名稱爲lib_opencv
,如下圖所示:
點擊next,不做操作繼續點擊finish
(PS:上述步驟是通用的Module
導入方式)
等待項目導入完成,切換到Android
視圖,導入成功的項目結構如下圖所示:
從上圖可以看出,目前lib_opencv
這個module
處於不可用狀態,我們修改該module
的build.gradle
文件,如下圖所示:
在這裏我們修改了lib_opencv
的構建類型爲library
,刪除了原始文件中包含的applicationid
,buildtoolsversion
信息,重新構建模塊即可發現該module
已經處於可用狀態,隨後在app
Module
內部依賴lib_opencv
Module
,app
Module
的build.gradle
文件如下圖:
至此我們就完成了OpenCV java 模塊的導入。
圖片灰度化
打開app模塊的MainActivity,在其onResume中進行OpenCV的初始化,代碼如下:
private ImageView mImageView;
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
super.onManagerConnected(status);
if (status == LoaderCallbackInterface.SUCCESS) {
//服務啓動成功,灰度化圖片顯示到ImageView上
filterImage();
}
}
};
Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.sample_image);
}
@Override
protected void onResume() {
super.onResume();
if (!OpenCVLoader.initDebug()) {
//啓動OpenCV服務
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION, getApplicationContext(), mLoaderCallback);
} else {
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
//灰度化圖片,暫不做代碼說明,複製即可
private void filterImage() {
Mat imgMat = null;
try {
imgMat = Utils.loadResource(this, R.drawable.demo);
Imgproc.cvtColor(imgMat, imgMat, Imgproc.COLOR_RGB2BGRA);
Mat resultMat = imgMat.clone();
Imgproc.Canny(imgMat, resultMat, 80, 90);
Bitmap bitmap = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultMat, bitmap);
mImageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
哇,看起來成功了,運行一下看下呢?
我去,OpenCV Manager
是個什麼鬼?原來OpenCV
考慮到應用包體積,提供了一個應用,其內部封裝了OpenCV
所需要的so
庫,那麼就沒有辦法不安裝OpenCV Manager
這個應用嗎?畢竟我們是面向用戶的,我們總不可能要求用戶下載我們的應用之前再去下載一個OpenCV Manager
吧?
作爲一個擁有OpenCV
源碼的開發,我們是站在上帝視角的,可以隨意造作,那麼自己加載OpenCV
的so
文件不就好,首先看下OpenCV
SDK
裏面的so
文件都在哪兒呢?在OPENCV_SDK_PATH/sdk/native/libs
下,廢話不多說,首先把該目錄下的所有文件拷貝到app
模塊的app/src/main/jniLibs
目錄下(jniLibs
目錄需新建,區分大小寫),如下圖所示:
隨後就是加載so
文件了,按理說OpenCV
SDK
裏面應該有so
包加載代碼或者類,搜索上圖中的opencv_java4.so
試下,果然找到了一個類,如下:
public class OpenCVNativeLoader implements OpenCVInterface {
public void init() {
System.loadLibrary("opencv_java4");
Logger.getLogger("org.opencv.osgi").log(Level.INFO, "Successfully loaded OpenCV native library.");
}
}
進而修改MainActivity
代碼如下:
private ImageView mImageView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mImageView = findViewById(R.id.sample_image);
new OpenCVNativeLoader().init();
}
@Override
protected void onResume() {
super.onResume();
filterImage();
}
private void filterImage() {
Mat imgMat = null;
try {
imgMat = Utils.loadResource(this, R.drawable.demo);
Imgproc.cvtColor(imgMat, imgMat, Imgproc.COLOR_RGB2BGRA);
Mat resultMat = imgMat.clone();
Imgproc.Canny(imgMat, resultMat, 80, 90);
Bitmap bitmap = Bitmap.createBitmap(resultMat.cols(), resultMat.rows(), Bitmap.Config.ARGB_8888);
Utils.matToBitmap(resultMat, bitmap);
mImageView.setImageBitmap(bitmap);
} catch (IOException e) {
e.printStackTrace();
}
}
運行下,有可能運行失敗,如果你是高版本的NDK
的話,就會應用崩潰,爆出如下錯誤:
這是因爲我們沒有指定C++
標準庫,在build.gradle defaultconfig
節點添加如下代碼(這裏就是剛開始新建爲C++
支持項目的原因,當然也可以選擇降低ndk
版本):
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
arguments "-DANDROID_STL=c++_shared"
}
}
運行效果如下:
關注公衆號,獲取Android開發最新博文,掃描下方二維碼加入吧: