1. 程式人生 > 其它 >Android配置OpenCV C++開發環境

Android配置OpenCV C++開發環境

1.下載OpenCV

網上的OpenCV配置環境大部分都不能正常配置成功,不是編譯時報找不到so,就是執行找不到so.本文是我試了不少坑才找到的配置方法.

其原理是讓AndroidStudio自己去編譯.mk檔案.生成所需的so庫.

先去OpenCV官網下載OpenCV的Android版本.速度慢的可以用迅雷下載.

OpenCV4.5.5

下載完成之後解壓到資料夾

2.AndroidStudio新建C++專案

新建專案選擇nativeC++模板.

C++標準選預設就好了

建立完成之如果之前沒配置過NDK可能會報錯.

開啟 Project Structue

切換到 SDK Location

標籤下,選擇一個已安裝的NDK即可.

如果沒有NDK可供選擇,需要先下載NDK.開啟 SDK Manager

選擇一個合適的版本下載就好,建議不要下載最新版本.

3.配置OpenCV開發環境

在配置OpenCV開發環境之前,可以安裝執行一下看一下有沒有報錯,第一次執行會有較長載入so庫的時間.

3.1配置include標頭檔案

找到之前解壓好的opencv-4.5.5-android-sdk資料夾,複製下面的 OpenCV-android-sdk\sdk\native\jni\include資料夾到 src/main/cpp資料夾下.

3.2配置CMakeLists.txt檔案

將以下內容複製替換到 cpp/CMakeLists.txt

注意將裡面的opencv路徑替換為自己電腦上的路徑.注意斜杆

cmake_minimum_required(VERSION 3.4.1)

# ##################### OpenCV 環境 ############################
#設定OpenCV-android-sdk路徑,替換為自己電腦上的路徑,注意是雙斜槓或者反斜槓
set( OpenCV_DIR D:\\Develop\\OpenCV\\opencv-4.5.5-android-sdk\\OpenCV-android-sdk\\sdk\\native\\jni )

find_package(OpenCV REQUIRED )
if(OpenCV_FOUND)
    include_directories(${OpenCV_INCLUDE_DIRS})
    message(STATUS "OpenCV library status:")
    message(STATUS "    version: ${OpenCV_VERSION}")
    message(STATUS "    libraries: ${OpenCV_LIBS}")
    message(STATUS "    include path: ${OpenCV_INCLUDE_DIRS}")
else(OpenCV_FOUND)
    message(FATAL_ERROR "OpenCV library not found")
endif(OpenCV_FOUND)

# ###################### 專案原生模組 ###########################

add_library( native-lib
        SHARED
        native-lib.cpp
)

#jnigraphics是Android bitmap處理庫,如果要通過jni傳遞bitmap物件,需要新增引用
target_link_libraries( native-lib
	${OpenCV_LIBS}
	log
        jnigraphics)

4.驗證OpenCV是否配置成功

4.1驗證標頭檔案是否配置成功

開啟 native-lib.cpp 匯入OpenCV的標頭檔案.如果有提示說明標頭檔案配置成功.

4.2驗證OpenCV庫是否正確連結到

開啟 native-lib.cpp 找到預設生成的stringFromJNI方法

extern "C" JNIEXPORT jstring JNICALL
Java_komine_demos_opencvdemo_MainActivity_stringFromJNI(JNIEnv* env,jobject /* this */) {
    //新增這行宣告
    cv::Mat mat;
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

執行如果沒有報錯說明OpenCV配置成功

4.3簡單使用OpenCV進行圖形處理

首先在 MainActivity中宣告一個processImage native方法,新版AndroidStudio再也不需要通過javac去生成程式碼了,

直接 Alt + Enter生成native的方法宣告,我的AndroidStudio版本是3.6.3,高於3.0的應該都能自動生成.

為了更方便使用OpenCV的類,可以匯入cv名稱空間

//寫在include語句的下方
using namespace cv;

native實現

extern "C"
JNIEXPORT void JNICALL
Java_komine_demos_opencvdemo_MainActivity_processImage(JNIEnv *env, jobject thiz,jstring image_path,jstring outPath) {
    //將jstring轉換為const char*
    const char* path = env->GetStringUTFChars(image_path,NULL);
    const char* imageOutPath = env->GetStringUTFChars(outPath,NULL);

    //讀取mat物件
    Mat sourceMat = imread(path);
    //灰度mat
    Mat grayMat;

    //將圖片轉換為灰度圖
    cvtColor(sourceMat,grayMat,COLOR_BGR2GRAY);

    //將圖片寫入到檔案
    imwrite(imageOutPath,grayMat);
}

佈局檔案

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
	xmlns:app="http://schemas.android.com/apk/res-auto"
	xmlns:tools="http://schemas.android.com/tools"
	android:layout_width="match_parent"
	android:layout_height="match_parent"
	android:orientation="vertical"
	tools:context=".MainActivity">

    <ImageView
        android:id="@+id/image"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
	/>

    <Button
        android:layout_width="wrap_content"
	android:layout_height="wrap_content"
	android:text="顯示灰度圖"
	android:onClick="loadGrayImage"
	/>

</LinearLayout>

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private ImageView mImageView;
    private String mOutputPath;

    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
	setContentView(R.layout.activity_main);

	mImageView = findViewById(R.id.image);

	//注意讀寫許可權,或者將圖片upload到files目錄
	String sourcePath = Environment.getExternalStorageDirectory() + File.separator + "miku.png";
	mOutputPath = Environment.getExternalStorageDirectory() + File.separator + "miku_gray.png";

	processImage(sourcePath,mOutputPath);
    }

    public void loadGrayImage(View view) {
        mImageView.setImageBitmap(BitmapFactory.decodeFile(mOutputPath));
    }

    public native void processImage(String imagePath,String outPath);
}

如果沒有檔案讀寫許可權程式就會在native層中斷,要驗證是否已經獲取到了許可權,可以打個斷點.如果計算結果為true說明有讀寫許可權.

效果圖