之前博文《Android學習筆記之——基於Android的opencv開發(Android studio3.6+opencv4.3.0開發環境搭建)》已經在Android studio中搭建了opencv的環境。本博文來進一步學習一下基於android的opencv開發
目錄
OpenCV Android SDK
OpenCV Android SDK 本質上是使用Java 語言接口通過JNI 技術調用OpenCV C++代碼完成的算法模塊。Open CV 4Android 本身並不是一個純Java 語言的計算機視覺庫,而是基於OpenCVC ++本地代碼、通過Java 語言接口定義,基於JNI 技術實現調
用C ++本地方法的SDK 開發包。所以當你下載好OpenCV Android SDK 之後,在它的SDK 目錄下可以看到如圖所示的目錄結構。
OpenCV Android SDK 的功能與Open CV 對應發佈版本中的功能完全相同,唯一不同的是因爲Java 語言的關係, Java 層封裝的接口的參數傳遞和方法調用,與C++的接口相比有一些差異,這些都是爲了更適應Java 語言的特性而做出的改動,使得Android 開發者更加容易學習與使用Open CV 來解決問題。
將OpenCV打包jar包的方法
之前博文《Android學習筆記之——基於Android的opencv開發(Android studio3.6+opencv4.3.0開發環境搭建)》完成了開發環境搭建,但是每次都要這樣操作就非常麻煩了,此處將opencv打包爲jar包
首先點擊右邊的gradle,如圖所示:
依次選擇430,other,如圖所示
找到create full jar debug (或者release),如圖
雙擊任意一個運行,運行完成後,改爲project視圖,在opencv430-bulid-intermediates-full_jar-debug下找到full_jar文件,如圖所示
把full_jar複製到app項目的libs下,如圖所示:
右鍵full.jar,add as a library,如圖
點擊ok
然後你就可以使用opencv中的Java接口,不用每次都Import Module了,如圖
測試代碼
package com.example.androidopencvtest;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import android.Manifest;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import org.opencv.android.OpenCVLoader;
import org.opencv.android.Utils;
import org.opencv.core.CvType;
import org.opencv.core.Mat;
import org.opencv.imgproc.Imgproc;
import org.opencv.android.CameraActivity;
import java.io.InputStream;
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
if (!OpenCVLoader.initDebug()) {
// System.loadLibrary("src/main/jniLibs");
// Handle initialization error
}
// System.loadLibrary("native-lib");
// System.loadLibrary("jniLibs");
// System.loadLibrary("src/main/jniLibs");
// System.loadLibrary("libs");
}
private double max_size = 1024;
private int PICK_IMAGE_REQUEST = 1;
private ImageView myImageView;
private Bitmap selectbp;
//權限
private static String[] PERMISSIONS_STORAGE = {
// Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,//寫權限
Manifest.permission.CAMERA//照相權限
};
@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();
}
private void selectImage() {
Intent intent = new Intent();
intent.setType("image/*");
intent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(intent,"選擇圖像..."), PICK_IMAGE_REQUEST);
}
});
//華爲手機攝像頭權限申請
//用於判斷SDK版本是否大於23
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.M){
//檢查權限
int i = ContextCompat.checkSelfPermission(this,PERMISSIONS_STORAGE[0]);
//如果權限申請失敗,則重新申請權限
if(i!= PackageManager.PERMISSION_GRANTED){
//重新申請權限函數
startRequestPermission();
Log.e("這裏","權限請求成功");
}
}
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();
}
});
}
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 startRequestPermission(){
//321爲請求碼
ActivityCompat.requestPermissions(this,PERMISSIONS_STORAGE,321);
}
}
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/activity_java"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity"
android:orientation="vertical"
>
<Button
android:id="@+id/select_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="選擇圖片" />
<Button
android:id="@+id/process_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="處理" />
<ImageView
android:id="@+id/imageView"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
還是不行,應該就是沒有將opencv的庫編譯進去
成功在手機上運行基於opencv的demo
加入下面的代碼
@Override //免安裝Opencv manager
protected void onResume() {
super.onResume();
if (!OpenCVLoader.initDebug()) {
System.out.println("Internal OpenCV library not found. Using OpenCV Manager for initialization");
OpenCVLoader.initAsync(OpenCVLoader.OPENCV_VERSION_3_4_0, this, mLoaderCallback);
} else {
System.out.println("OpenCV library found inside package. Using it!");
mLoaderCallback.onManagerConnected(LoaderCallbackInterface.SUCCESS);
}
}
// OpenCV庫加載並初始化成功後的回調函數
private BaseLoaderCallback mLoaderCallback = new BaseLoaderCallback(this) {
@Override
public void onManagerConnected(int status) {
switch (status) {
case LoaderCallbackInterface.SUCCESS: {
System.out.println("OpenCV loaded successfully");
}
break;
default: {
super.onManagerConnected(status);
}
break;
}
}
};
加上上邊這段代碼,下邊這兩個方法就是判斷是否已經存在OpenCv庫,存在就是用打包好的,不存在就下載。然後就ok啦~
接下來基本就可以將之前學過的opencv相關的開發移植到手機上了哈~
參考資料
https://blog.csdn.net/qq_39321542/article/details/106080136
https://blog.csdn.net/lhhnb/article/details/89705989
https://blog.csdn.net/lhhnb/article/details/94896434