一、知識準備:
1.了解Android工程如何運作在裝置上
2.了解C/C++編譯過程,能夠讀懂makefile
二、實作流程:
1.打開Eclipse,建立一個空白的Android工程:
項目名稱為OpenCV_Test:
2.為建立工程引入OpenCV Library - 3.1.0庫工程:
選擇工程,右鍵點選Properties(屬性),然後在Android頁簽中,用Add功能添加一個庫工程引用。
3.打開src目錄下面的MainActivity,由于我們的目标是在應用中通過OpenCV的
JavaAPI實作打開相機全屏顯示,并擷取預覽框,是以MainActivity需要實作CvCameraViewListener2接口,可以實作三個方法,分别是:onCameraViewStarted、onCameraViewStopped和onCameraFrame,關鍵的圖像處理寫在onCameraFrame函數中:
4.修改AndroidManifest.xml檔案:
添加相機的相關權限:
[java]
view
plain
copy print ? https://code.csdn.net/snippets/1655010 https://code.csdn.net/snippets/1655010/fork- <uses-permission android:name="android.permission.CAMERA"/>
- <uses-feature android:name="android.hardware.camera" android:required="false"/>
- <uses-feature android:name="android.hardware.camera.autofocus" android:required="false"/>
設定應用的界面主題為沒有頂部标題欄且全屏顯示的,在application标簽中添加:
https://code.csdn.net/snippets/1655010 https://code.csdn.net/snippets/1655010/fork- <application
- android:allowBackup="true"
- android:icon="@drawable/ic_launcher"
- android:label="@string/app_name"
- android:theme="@android:style/Theme.NoTitleBar.Fullscreen" >
5.為界面布局檔案添加顯示相機内容的元件:
打開res/layout下面的activity_main.xml布局檔案,往布局中添加一個OpenCV的視覺元件JavaCameraView:
https://code.csdn.net/snippets/1655010 https://code.csdn.net/snippets/1655010/fork- <RelativeLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- xmlns:opencv="http://schemas.android.com/apk/res-auto"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
- <org.opencv.android.JavaCameraView
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:id="@+id/camera_view"
- opencv:show_fps="true"
- opencv:camera_id="any"/>
- </RelativeLayout>
6.回到MainActivity中,完成API的調用:
聲明一個CameraBridgeViewBase對象,用于存放activity_main.xml中的JavaCameraView元件,并在OnCreate中實作綁定和添加事件監聽:
- mCVCamera = (CameraBridgeViewBase) findViewById(R.id.camera_view);
- mCVCamera.setCvCameraViewListener(this);
7.添加C/C++編譯支援,即Add Native Support,這是為了不依賴于OpenCV Manager,直接引入庫檔案進行編譯:
記住這裡的填寫的名稱就是引入的庫檔案被編譯生成.so檔案的名稱:
打開生成的jni目錄下的Android.mk檔案,這個是C/C++編譯和連結時使用到的makefile配置檔案,稍微做一點點修改内容,在“include $(CLEAR_VARS)”後面添加以下内容:
https://code.csdn.net/snippets/1655010 https://code.csdn.net/snippets/1655010/fork- OPENCV_CAMERA_MODULES:=on
- OPENCV_INSTALL_MODULES:=on
- OPENCV_LIB_TYPE:=SHARED
- ifdef OPENCV_ANDROID_SDK
- ifneq ("","$(wildcard $(OPENCV_ANDROID_SDK)/OpenCV.mk)")
- include ${OPENCV_ANDROID_SDK}/OpenCV.mk
- else
- include ${OPENCV_ANDROID_SDK}/sdk/native/jni/OpenCV.mk
- endif
- else
- include ../../sdk/native/jni/OpenCV.mk
- endif
如此,我們就完成了庫檔案的引入操作,那麼接下來就是讓相機的輸入幀展示在預覽元件JavaCameraView上。
8.修改public Mat onCameraFrame(CvCameraViewFrame inputFrame)回調函數的内容了,這個函數在相機重新整理每一幀都會調用一次,而且每次的輸入參數就是目前相機視圖資訊,我們直接擷取其中的RGBA資訊作為Mat資料傳回給顯示元件即可:
- /**
- * 圖像處理都寫在此處
- */
- @Override
- public Mat onCameraFrame(CvCameraViewFrame inputFrame) {
- //直接傳回輸入視訊預覽圖的RGBA資料并存在Mat資料中
- return inputFrame.rgba();
- }
9.以上操作中,我們在OnCreate函數中已經擷取到mCVCamera對象,隻有調用mCVCamera.enableView()之後,預覽元件才會顯示每一幀的Mat圖像,但是在顯示之前我們必須先確定OpenCV的庫檔案已經加載完成,是以調用此方法需要進行異步處理:
- * 通過OpenCV管理Android服務,異步初始化OpenCV
- BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
- @Override
- public void onManagerConnected(int status){
- switch (status) {
- case LoaderCallbackInterface.SUCCESS:
- Log.i(TAG,"OpenCV loaded successfully");
- mCVCamera.enableView();
- break;
- default:
- }
- }
- };
是以隻有當mLoaderCallback收到LoaderCallbackInterface.SUCCESS消息的時候,才會打開預覽顯示,那麼這個消息是從哪裡發出來的呢,這就需要我們重寫Activity的onRusume方法了,因為每次目前Activity激活都會調用此方法,是以可以在此處檢測OpenCV的庫檔案是否加載完畢:
- @Override
- public void onResume() {
- super.onResume();
- if (!OpenCVLoader.initDebug()) {
- Log.d(TAG,"OpenCV library not found!");
- } else {
- Log.d(TAG, "OpenCV library found inside package. Using it!");
- mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
三、結果展示:
至此,我們就完成了裝置相機打開以及輸入預覽資料的擷取,運作在裝置上可以看到: