Android+JNI配置OpenCV(简化版)
所用版本:
Android Studio 4.1.3
OpenCV-Android-sdk 4.1.0
NDK 22.1.7171670
如图:创建一个C++项目,点击Next,然后选择C++14,然后要看下NDK,如果没有NDK的话,先安装NDK。
然后如图打开cpp下的CMakeLists.txt,将下面的代码替换掉里面的代码,这里需要修改
set(OpenCV_DIR D:\\android4.1.0-opencv\\OpenCV-android-sdk\\sdk\\native\\jni)
将这一行的代码改成自己的sdk的路径
cmake_minimum_required(VERSION 3.4.1)
# ##################### OpenCV 环境 ############################
#设置OpenCV-android-sdk路径
set(OpenCV_DIR D:\\android4.1.0-opencv\\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)
#set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl, --exclude-libs, libippicv.a -Wl, --exclude-libs, libippiw.a")
# ###################### 项目原生模块 ###########################
add_library(native-lib
SHARED
native-lib.cpp cameraCal.cpp)
target_link_libraries(native-lib
${OpenCV_LIBS}
log
jnigraphics)
然后打开app下的build.gradle,将图片中的位置修改为下面的代码。
externalNativeBuild {
cmake {
cppFlags "-std=c++14 -frtti -fexceptions"
arguments "-DANDROID_STL=gnustl_shared" // 支持C++异常处理模板库
arguments "-DANDROID_STL=c++_shared"
abiFilters "x86_64", "armeabi-v7a", "arm64-v8a"
}
}
到这里就配置完了,然后就可以编写代码了,写一个简单的测试代码。
先打开java下的MainActivity
首先加一个读取bitmap图像的函数
private static Bitmap getBitmap(Context context, int vectorDrawableId) {
Bitmap bitmap = null;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP) {
Drawable vectorDrawable = context.getDrawable(vectorDrawableId);
bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
Canvas canvas = new Canvas(bitmap);
vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
vectorDrawable.draw(canvas);
} else {
bitmap = BitmapFactory.decodeResource(context.getResources(), vectorDrawableId);
}
return bitmap;
}
然后将原本的调用函数注释掉,将bitmap传给CPP
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
// tv.setText(stringFromJNI());
Bitmap bitmap = getBitmap(MainActivity.this, R.drawable.a);
int w = bitmap.getWidth(), h = bitmap.getHeight();
int[] pix = new int[w * h];
bitmap.getPixels(pix, 0, w, 0, 0, w, h);
String result = getImgFromJNI(pix, w, h);
tv.setText(result);
}
在这里放一张图片,Bitmap bitmap = getBitmap(MainActivity.this, R.drawable.a);
将图片的名字改成自己图像的名字
然后打开CPP文件,将函数名改成与java相同的名字
如图导入opencv的库,然后接收data,并转换为Mat,然后就是C++的OpenCV的操作了。代码如下,我只做了一步灰度,然后将灰度图的宽返回。
#include <jni.h>
#include <string>
#include <opencv2/opencv.hpp>
extern "C" JNIEXPORT jstring JNICALL
Java_com_example_newandroidjniopencv_MainActivity_getImgFromJNI(
JNIEnv* env,
jobject /* this */, jintArray data_, jint w, jint h) {
jint *data;
data = env->GetIntArrayElements(data_, NULL);
cv::Mat img(h, w, CV_8UC3, data);
cv::Mat gray;
cv::cvtColor(img, gray, cv::COLOR_BGR2GRAY);
double k = gray.cols;
std::string ks = std::to_string(k);
return env->NewStringUTF(ks.c_str());
}
看下运行结果。成功了。