網上的OpenCV配置環境大部分都不能正常配置成功,不是編譯時報找不到so,就是運行找不到so.本文是我試了不少坑才找到的配置方法.其原理是讓AndroidStudio自己根據mk文件自動配置. 1.下載OpenCV 先去OpenCV官網下載OpenCV的Android版本.速度慢的可以用迅雷下載. ...
網上的OpenCV配置環境大部分都不能正常配置成功,不是編譯時報找不到so,就是運行找不到so.本文是我試了不少坑才找到的配置方法.其原理是讓AndroidStudio自己根據mk文件自動配置.
1.下載OpenCV
先去OpenCV官網下載OpenCV的Android版本.速度慢的可以用迅雷下載.
下載完成之後解壓到文件夾
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 thiz) {
//添加這行聲明
cv::Mat mat;
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
運行如果沒有報錯說明OpenCV配置成功
4.3簡單使用OpenCV進行圖片處理
首先在 MainActivity
中聲明一個processImage native方法,新版AndroidStudio再也不需要通過javah去生成頭文件了,
直接 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);
}
效果圖