2014年8月22日 星期五

建立Android App並使用OpenCV函式庫

在執行完OpenCV4Android的範例程式後,接著來介紹如何自己建立一個使用OpenCVApp

由於OpenCV是由C/C++編譯出來的函式庫,如果想要在Android上面呼叫OpenCV函式庫的函式,就必須先將對應版本的函式庫檔案放進去專案裡面。
可是,每一次編譯Android App都要將函式庫包進去apk(AndroidApp安裝檔)裡面,接著再將安裝檔傳到手機中進行重新安裝,這是非常消耗資源的一件事情。
Android上要使用OpenCV的函式庫, OpenCV的官網上有提供兩個方法[1],第一個是透過使用由OpenCV官方所提供”OpenCV Manager”App,這套App會先將OpenCV的函式庫檔案下載進去手機,往後的App如果有使用OpenCV函式庫,會在App執行的時候載入當時所下載的函式庫並進行呼叫;另外一個方法是上面一開始所提到的,將OpenCV函式庫包入自行開發的App,這個方法比較推薦往後要將App發行給其他使用者的時候,就不必請其他使用者下載”OpenCV Manager”App
在這篇文章是介紹第一個使用”OpenCV Manager”來進行呼叫OpenCV函式庫的函式,開發的時候會比起另一個方法更為方便。


()建立Android App並使用OpenCV函式庫(將彩色影像轉成灰階並顯示)
1.Eclipse上建立一個新的Android Application專案。
(1)建立Android Application


Step1:開啟ADT裡面的Eclipse,在這邊的例子是使用”C:\Document and Setting\Administrator\workspace”來當成專案的根目錄。












Step2:建立專案。
















應用程式名稱(Application Name)HelloOpenCV4Android
專案名稱(Project Name)HelloOpenCV4Android
Package Namecom.example.helloopencv4android(建議讓Eclipse自動產生)
最小需求的平台(Minimum Required SDK)API11 Android 3.0
目標平台(Target SDK)API14 Android 4.0
編譯平台(Compile With)API14 Android 4.0

























產生一個空白的頁面(Blank Activity)















頁面名稱(Activity Name)MainActivity














(2)新增ImageView控制項作為顯示處理的結果影像。
Step3:滑鼠左鍵雙點擊"HelloOpenCV4Android/res/layout/activity_main.xml"之後,會看到activity_main所儲存的layout以及其圖像預覽結果(Graphical Layout),將Images & Media類別中的ImageVIew以拖曳的方式移到右邊的預覽圖之中。











Step4:將ImageView拖曳至預覽圖之中之後,Eclipse會請使用者選擇預設影像,在這邊的範例是使用預設值(黑色)













Step5:按下OK之後,在預覽圖之中就會產生一個以黑色為底的ImageView控制項。











Step6:將顯示方式由Graphical Layout變更至其右邊的activity_main.xml之後,可以看到剛剛所新增的ImageView控制項與預設的TextView控制項之屬性資料。











Step7:由於在這個範例不需要使用文字來呈現,所以將TextView的資料砍掉,並且將ImageViewlayout_witdhlayout_height屬性變更至”fill_parent”(填滿父控制項)











(3)將要轉成灰階的影像(lena.jpg)放入專案之中。
Step8:先將lena.jpg複製到專案的res\drawable-dhpi資料夾之中,以這個例子來講,完整路徑: "C:\Document and Setting\Administrator\workspace\HelloOpenCV4Android\res\drawable-dhpi"

















Step9:在Eclipse上,對專案的res資料夾使用滑鼠右鍵點擊並選擇更新(Refresh),這樣Eclipse就會幫使用者新增專案的變數,讓使用者方便使用那一個變數進行讀取。





















(4)設定OpenCVjar(java的函式庫檔案),並將OpenCV設定成與App一起編入apk之中。
Step10:對專案的資料夾滑鼠右鍵點擊並選擇屬性(Properties)





















Step11:在Java Build Path的類別上,選擇Libraries頁面,並點選Add External JARs…













Step12:選擇OpenCV4Androidsdk\java\bin\opencv library – 2.4.9.jar(一定要先完成OpenCV4Android的範例程式才會產生)













Step13:新增完成後,選擇Order and Export的頁面,將opencv library – 2.4.9.jar的選項打勾,這樣才會將opencv library – 2.4.9包在這個專案。













Step14:由於編譯器的設定已經變更,接下來Eclipse會需要重建整個專案。













(5)新增將圖片轉為灰階的程式碼並連上手機進行測試。
Step15:在MainActivity.java之中新增以下程式碼。
由於OpenCV函式庫是使用C/C++所編譯而成的函式庫,所以在Java端必須先載入OpenCV函式庫到這個App之後方能使用OpenCV的函式,以下是Java載入OpenCV函式庫的程式碼(包含轉灰階並顯示)
    //非同步載入OpenCV函式庫
    private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                 System.out.println("load opencv lib SUCCESS!!");
                 //從resource讀取影像
                 InputStream is = getResources().openRawResource(R.drawable.lena);
              Bitmap img = BitmapFactory.decodeStream(is);
              if (img != null) {
               Mat m = new Mat() ,
             grayM = new Mat() ;
               //將bitmap轉成OpenCV的Mat型態
            Utils.bitmapToMat(img, m);
            //將影像轉換成灰階
            Imgproc.cvtColor(m, grayM, Imgproc.COLOR_BGR2GRAY);
               //因為Android顯示的時候需要使用BGRA的格式 所以必須將灰階(channel = 1)擴展成BGRA(channel = 4)
            Imgproc.cvtColor(grayM, m, Imgproc.COLOR_GRAY2BGRA);
               //將OpenCV的Mat型態轉成Bitmap型態
               Bitmap bm = Bitmap.createBitmap(m.cols(), m.rows(),Bitmap.Config.ARGB_8888);
               Utils.matToBitmap(m, bm);
               //尋找貼圖的ImageView
               ImageView iView = (ImageView) findViewById(R.id.imageView1) ;
               //將圖片設定到ImageView
               iView.setImageBitmap(bm) ;
               //釋放暫存的影像記憶體空間
               m.release();
               grayM.release() ;
               img.recycle() ;
              }
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
MainActivityonCreate的事件上新增:
//非同步初始化OpenCV
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9 , this , mLoaderCallback ) ;













完整的程式碼:
package com.example.helloopencv4android;

import java.io.InputStream;

import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.LoaderCallbackInterface;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;

import android.support.v7.app.ActionBarActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.ImageView;


public class MainActivity extends ActionBarActivity {
 
 //非同步載入OpenCV函式庫
    private BaseLoaderCallback  mLoaderCallback = new BaseLoaderCallback(this) {
        @Override
        public void onManagerConnected(int status) {
            switch (status) {
                case LoaderCallbackInterface.SUCCESS:
                {
                 System.out.println("load opencv lib SUCCESS!!");
                 //從resource讀取影像
                 InputStream is = getResources().openRawResource(R.drawable.lena);
              Bitmap img = BitmapFactory.decodeStream(is);
              if (img != null) {
               Mat m = new Mat() ,
             grayM = new Mat() ;
               //將bitmap轉成OpenCV的Mat型態
            Utils.bitmapToMat(img, m);
            //將影像轉換成灰階
            Imgproc.cvtColor(m, grayM, Imgproc.COLOR_BGR2GRAY);
               //因為Android顯示的時候需要使用BGRA的格式 所以必須將灰階(channel = 1)擴展成BGRA(channel = 4)
            Imgproc.cvtColor(grayM, m, Imgproc.COLOR_GRAY2BGRA);
               //將OpenCV的Mat型態轉成Bitmap型態
               Bitmap bm = Bitmap.createBitmap(m.cols(), m.rows(),Bitmap.Config.ARGB_8888);
               Utils.matToBitmap(m, bm);
               //尋找貼圖的ImageView
               ImageView iView = (ImageView) findViewById(R.id.imageView1) ;
               //將圖片設定到ImageView
               iView.setImageBitmap(bm) ;
               //釋放暫存的影像記憶體空間
               m.release();
               grayM.release() ;
               img.recycle() ;
              }
                } break;
                default:
                {
                    super.onManagerConnected(status);
                } break;
            }
        }
    };
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        //非同步初始化OpenCV
        OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_2_4_9 , this , mLoaderCallback ) ;
        
    }
    
    
    

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }
}

Step16:對專案的資料夾滑鼠右鍵點擊並選擇Run As->Android Application執行這隻程式。





















Step17:選擇執行這隻程式的機器。













(6)手機端應用程式執行的流程。
Step18:手機執行這支App之後,發現手機上沒有安裝”OpenCV Manager”,會要求使用者進行安裝。





















Step19:進入Google Play商店之後,直接點選安裝,等到下載並安裝結束即可。





















Step20:再次進入App,就可以看到lena轉成灰階的影像。





















參考連結
[1]:Android development with OpenCV

沒有留言: