一、下载opencv源码(以4.2.0为例)
https://github.com/opencv/opencv/releases
https://github.com/opencv/opencv_contrib/tags
二、配置电脑环境
环境要求
java 1.8
Android SDK Tools 25.2.5
Android SDK Build Tools 21.1.2
Android SDK target(sdk platform) 26
Android NDK 18.1.5063045
Android Cmake 3.31.1
mingw64
apache-ant-1.10.15
配置环境变量(替换成自己的路径)
D:\software\mingw64\bin
D:\software\apache-ant-1.10.15\bin
D:\software\sdk_tools_25.2.5\cmake\3.31.1\bin
三、新建android studio项目
新建时选择NativeC++项目类型,将opencv源码都解压到根目录下
四、编译
在opencv-4.2.0文件夹里新建build文件夹并cd进去执行编译命令。
生成Ninja构建脚本:(替换成自己的路径,版本建议保持一致,cmake -LA可以检查哪些变量可用)
cmake ^
-GNinja ^
-H"D:/gitc/NLOpenCV/opencv-4.2.0" ^
-DCMAKE_MAKE_PROGRAM="D:/software/sdk_tools_25.2.5/cmake/3.31.1/bin/ninja.exe" ^
-DCMAKE_INSTALL_PREFIX="D:/gitc/NLOpenCV/OpenCV-android-sdk" ^
-DANDROID_PROJECT_BUILD_TYPE="ANT" ^
-DBUILD_ANDROID_PROJECTS=ON ^
-DBUILD_EXAMPLES=OFF ^
-DBUILD_TESTS=OFF ^
-DBUILD_PERF_TESTS=OFF ^
-DBUILD_JAVA=ON ^
-DBUILD_opencv_java=ON ^
-DBUILD_SHARED_LIBS=OFF ^
-DBUILD_FAT_JAVA_LIB=ON ^
-DBUILD_PYTHON=OFF ^
-DINSTALL_ANDROID_EXAMPLES=OFF ^
-DANDROID_EXAMPLES_WITH_LIBS=OFF ^
-DBUILD_DOCS=OFF ^
-DWITH_OPENCL=ON ^
-DANDROID_NDK="D:/software/sdk_tools_25.2.5/ndk/18.1.5063045" ^
-DANDROID_SDK="D:/software/sdk_tools_25.2.5" ^
-DCMAKE_TOOLCHAIN_FILE="D:/software/sdk_tools_25.2.5/ndk/18.1.5063045/build/cmake/android.toolchain.cmake" ^
-DOPENCV_EXTRA_MODULES_PATH="D:/gitc/NLOpenCV/opencv_contrib-4.2.0/modules" ^
-DANDROID_TOOLCHAIN=clang ^
-DANDROID_STL=c++_static ^
-DANDROID_ARM_NEON=ON ^
-DANDROID_ABI=arm64-v8a ^
-DANDROID_NATIVE_API_LEVEL=21 ^
-DBUILD_opencv_python3=OFF ^
-DBUILD_opencv_python2=OFF ^
-DOPENCV_ENABLE_NONFREE=ON
使用 Ninja 构建系统命令:
ninja -j16
安装构建后的二进制文件到指定目录(也就是上面配置的DCMAKE_INSTALL_PREFIX的文件夹OpenCV-android-sdk)
ninja install
五、集成到as项目
1.将OpenCV-android-sdk/sdk当module导入项目
2.将OpenCV-android-sdk/sdk/native/jni/include文件夹拷贝到你的项目中src/main/cpp下面
3.在app\src\main\cpp\CMakeLists.txt中修改
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
native-lib.cpp)
#opencv
set(OPENCV_LIBS_DIR ${CMAKE_SOURCE_DIR}/../cpp/include)
set(OPENCV_LIBS ${CMAKE_SOURCE_DIR}/../jniLibs)
add_library(libopencv_java4
SHARED
IMPORTED )
set_target_properties(libopencv_java4
PROPERTIES IMPORTED_LOCATION
${OPENCV_LIBS}/${ANDROID_ABI}/libopencv_java4.so )
#指定引入头文件目录
include_directories(${OPENCV_LIBS_DIR})
find_library( # Sets the name of the path variable.
log-lib
log)
target_link_libraries( # Specifies the target library.
${CMAKE_PROJECT_NAME}
libopencv_java4
jnigraphics #JNI层,添加bitmap支持
${log-lib})
4.将OpenCV-android-sdk/sdk/native/libs里的文件拷贝到你的项目中src/main/jniLibs下面。并修改名字为jniLibs。
5.build.gradle(:app)的Android下添加
sourceSets{
main{
jniLibs.srcDirs = ['src/main/jniLibs']
}
}
6.将build.gradle的compileSdk、minSdkVersion、targetSdk修改跟app的一致
7.build.gradle(:OpenCV)的Android下添加
namespace 'org.opencv'
8.拷贝OpenCV-android-sdk\sdk\java\src\org\opencv\engine\OpenCVEngineInterface.aidlapp/src/aidl/org/opencv/engine/OpenCVEngineInterface.aidl
9.build.gradle(:OpenCV)的Android下添加
buildFeatures {
aidl true
}
10.gradle.properties中添加android.defaults.buildfeatures.buildconfig=true
11.注释掉androidManifest.xml(:OpenCV)的<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="21" />
12.删除androidManifest.xml(:OpenCV)的package="org.opencv"
13.build.gradle(:OpenCV)中修改
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
最终目录结构如下图
六、jni调用opencv函数实现高斯模糊
native-lib.cpp
#include <jni.h>
#include <string>
#include <android/bitmap.h>
#include <opencv2/opencv.hpp>
using namespace cv;
extern "C"
JNIEXPORT void JNICALL
Java_com_newlink_nlopencv_MainActivity_opencvTest(
JNIEnv *env,jclass clazz,
jobject bitmap) {
AndroidBitmapInfo info;
void *pixels;
CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0);
//判断图片是位图格式有RGB_565 、RGBA_8888
CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 ||
info.format == ANDROID_BITMAP_FORMAT_RGB_565);
CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0);
CV_Assert(pixels);
//将bitmap转化为Mat类
Mat image(info.height, info.width, CV_8UC4, pixels);
// 调用opencv函数进行高斯模糊
GaussianBlur(image, image, Size(101, 101), 0);
}
MainActivity.java
package com.newlink.nlopencv;
import androidx.appcompat.app.AppCompatActivity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import com.newlink.nlopencv.databinding.ActivityMainBinding;
public class MainActivity extends AppCompatActivity {
// Used to load the 'nlopencv' library on application startup.
static {
System.loadLibrary("nlopencv");
}
private ActivityMainBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = ActivityMainBinding.inflate(getLayoutInflater());
setContentView(binding.getRoot());
Bitmap Original_bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.img);
ImageView Original_image=findViewById(R.id.Original_image);
Original_image.setImageBitmap(Original_bitmap);
Button button=findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
opencvTest(bitmap);
ImageView Image=findViewById(R.id.Image);
Image.setImageBitmap(bitmap);
}
});
}
public static native void opencvTest(Object bitmap);
}
activity_main.xml
<?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"
tools:context=".MainActivity"
android:orientation="vertical">
<ImageView
android:id="@+id/Original_image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
<Button
android:id="@+id/button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="高斯模糊"/>
<ImageView
android:id="@+id/Image"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
/>
</LinearLayout>
效果如下