OpenCV On Android開發 – Android Studio上環境配置

OpenCV On Android開發 – Android Studio上環境配置

在Android Studio 2.2上整合OpenCV4Android SDK

OpenCV官方的教程是基於Eclipse配置開發環境,但是Eclipse已經被Google拋棄了,所以我是寫這篇文章的前三天剛剛開始用Android Studio 2.2版本,很多Gradle指令碼也不熟悉,只能各種查詢。經過一番痛苦的領悟終於把OpenCV4Android整合到我在Android Studio中建立的專案上了,並且寫了測試程式。下面說一下如何實現整合步驟,首先是準備工作要做好:

  • 下載好Android Studio 2.2版本
  • 下載好OpenCV4AndroidSDK – 去OpenCV社群官網即可得到。
  • 下載之後解壓縮到D:\OpenCV-2.4.11-android-sdk\OpenCV-android-sdk
    這裡寫圖片描述
  • apk目錄裡面放的是OpenCV Manager的安裝檔案,是不同CPU版本要選擇不同apk安裝檔案,這種方式呼叫OpenCV比較麻煩。不推薦!

  • doc目錄裡面放的是相關文件與OpenCV的LOGO

  • samples裡面放的是OpenCV4Android的演示程式碼,參考價值很大,值得關注

  • sdk裡面放內容就是我們要重點關注的,整合到Android Studio中的專案上去的東西。
    雙擊開啟sdk資料夾就會看到:
    這裡寫圖片描述

準備工作做好之後,首先就是要在Android Studio中建立一個Android專案,建立好之後,選擇File->New->Import Module
這裡寫圖片描述
然後選擇到SDK路徑下的JAVA
這裡寫圖片描述
匯入之後,你就會看到
這裡寫圖片描述
就說明成功匯入了,然後開啟Module Settings
這裡寫圖片描述

新增依賴之後,就可以在專案中引用OpenCV相關API程式碼了,如果你此刻執行測試apk程式,它就會提示你安裝OpenCV Manager這個東西。對多數開發者來說這不算配置成功,這樣自己的APP就無法獨立安裝,必須依賴OpenCV Manager這個apk檔案才可以執行,這個時候就該放大招來解決這個問題,首先把我們準備階段看到SDK下面native檔案下所有的檔案都copy到你建立好的專案libs目錄下,然後在gradle中加上如下一段指令碼:
這裡寫圖片描述

task nativeLibsToJar(type: Jar, description: 'create a jar archive of the native libs') {
destinationDir file("$buildDir/native-libs")
baseName 'native-libs'
from fileTree(dir: 'libs', include: '**/*.so')
into 'lib/'
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn(nativeLibsToJar)
}

然後還要加上這句話:

compile fileTree(dir: "$buildDir/native-libs", include: 'native-libs.jar')

最後一步,檢查一下gradle檔案:
這裡寫圖片描述
如此配置之後你就再也不需要其它任何配置了,這樣既避免了NDK繁瑣又不用依賴OpenCV Manager第三方APP,你的APP就可以直接使用OpenCV了。

特別說明:
此配置方式OpenCV載入必須通過靜態載入方式,以下為Demo測試程式程式碼:

package com.example.administrator.helloworld;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.annotation.NonNull;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.support.v7.view.ActionMode;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import org.opencv.android.BaseLoaderCallback;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.Core;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.imgproc.Imgproc;
import java.io.InputStream;
import static android.widget.Toast.makeText;
public class MainActivity extends AppCompatActivity {
private double max_size = 1024;
private int PICK_IMAGE_REQUEST = 1;
private ImageView myImageView;
private Bitmap selectbp;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
staticLoadCVLibraries();
myImageView = (ImageView)findViewById(R.id.imageView);
myImageView.setScaleType(ImageView.ScaleType.FIT_CENTER);
Button selectImageBtn = (Button)findViewById(R.id.select_btn);
selectImageBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// makeText(MainActivity.this.getApplicationContext(), "start to browser image", Toast.LENGTH_SHORT).show();
selectImage();
}
});
Button processBtn = (Button)findViewById(R.id.process_btn);
processBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// makeText(MainActivity.this.getApplicationContext(), "hello, image process", Toast.LENGTH_SHORT).show();
convertGray();
}
});
}
//OpenCV庫靜態載入並初始化
private void staticLoadCVLibraries(){
boolean load = OpenCVLoader.initDebug();
if(load) {
Log.i("CV", "Open CV Libraries loaded...");
}
}
private void convertGray() {
Mat src = new Mat();
Mat temp = new Mat();
Mat dst = new Mat();
Utils.bitmapToMat(selectbp, src);
Imgproc.cvtColor(src, temp, Imgproc.COLOR_BGRA2BGR);
Log.i("CV", "image type:"   (temp.type() == CvType.CV_8UC3));
Imgproc.cvtColor(temp, dst, Imgproc.COLOR_BGR2GRAY);
Utils.matToBitmap(dst, selectbp);
myImageView.setImageBitmap(selectbp);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode == PICK_IMAGE_REQUEST && resultCode == RESULT_OK && data != null && data.getData() != null) {
Uri uri = data.getData();
try {
Log.d("image-tag", "start to decode selected image now...");
InputStream input = getContentResolver().openInputStream(uri);
BitmapFactory.Options options = new BitmapFactory.Options();
options.inJustDecodeBounds = true;
BitmapFactory.decodeStream(input, null, options);
int raw_width = options.outWidth;
int raw_height = options.outHeight;
int max = Math.max(raw_width, raw_height);
int newWidth = raw_width;
int newHeight = raw_height;
int inSampleSize = 1;
if(max > max_size) {
newWidth = raw_width / 2;
newHeight = raw_height / 2;
while((newWidth/inSampleSize) > max_size || (newHeight/inSampleSize) > max_size) {
inSampleSize *=2;
}
}
options.inSampleSize = inSampleSize;
options.inJustDecodeBounds = false;
options.inPreferredConfig = Bitmap.Config.ARGB_8888;
selectbp = BitmapFactory.decodeStream(getContentResolver().openInputStream(uri), null, options);
myImageView.setImageBitmap(selectbp);
} catch (Exception e) {
e.printStackTrace();
}
}
}
private void selectImage() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"選擇影象..."), PICK_IMAGE_REQUEST);
}
}

選擇一張影象載入之後顯示:
這裡寫圖片描述

點選【處理】之後,通過呼叫OpenCV API實現了灰度轉換
這裡寫圖片描述

特別說明:這種方式呼叫OpenCV無需NKD以及安裝OpenCV Manager。應該是廣大Android開發人員最喜歡的一種方式。
免費環境搭建視訊檢視
OpenCV For Android 基礎入門視訊