一、创建NDK工程
- 创建Android工程:
创建一个NDK工程:
讯享网 - 配置NDK支持:
- 打开项目中的
build.gradle文件(通常是在app模块的目录下)。 - 在
android块中添加以下代码,指定CMake版本和NDK版本:
- 打开项目中的
apply plugin: 'com.android.application' android {
compileSdkVersion 24 buildToolsVersion "29.0.2" defaultConfig {
applicationId "com.dashu.scanjia" archivesBaseName = "$applicationId" ndk {
moduleName "ScanJiaLib" abiFilters "armeabi-v7a", "arm64-v8a" } minSdkVersion 24 } externalNativeBuild {
cmake {
version "3.10.2" path file('src/main/jni/CMakeLists.txt') } } } dependencies {
implementation 'com.android.support:support-annotations:28.0.0' }
讯享网
- 创建C/C++代码文件夹:
- 在项目的
app/src/main目录下,创建一个名为cpp的文件夹。 - 在
cpp文件夹中,创建一个C或C++文件,例如native-lib.cpp。

- 在项目的
- 配置CMakeLists.txt:
- 在
app模块的目录下,创建一个名为CMakeLists.txt的文件,把所有用到的库依赖都使用这个make进行导入,我这里导入了onnxruntime ,OpenCV,Ncnn,还有把自己编写的C++代码也导入,导入的C++代码只要.cpp文件。
- 在
讯享网project(ScanJiaLib) cmake_minimum_required(VERSION 3.4.1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp") if(DEFINED ANDROID_NDK_MAJOR AND ${ANDROID_NDK_MAJOR} GREATER 20) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-openmp") endif() opencv 库 set(OpenCV_DIR "${CMAKE_SOURCE_DIR}/sdk/native/jni") find_package(OpenCV REQUIRED) if (OpenCV_FOUND) message(STATUS "OpenCV_LIBS: ${OpenCV_LIBS}") message(STATUS "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}") else () message(FATAL_ERROR "opencv Not Found!") endif (OpenCV_FOUND) include(${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime-shared/OnnxRuntimeWrapper.cmake) find_package(OnnxRuntime REQUIRED) if (OnnxRuntime_FOUND) message(STATUS "OnnxRuntime_LIBS: ${OnnxRuntime_LIBS}") message(STATUS "OnnxRuntime_INCLUDE_DIRS: ${OnnxRuntime_INCLUDE_DIRS}") else () message(FATAL_ERROR "onnxruntime Not Found!") endif (OnnxRuntime_FOUND) #ncnn库 set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn--android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn) find_package(ncnn REQUIRED) set_target_properties( ncnn PROPERTIES INTERFACE_COMPILE_OPTIONS "-frtti;-fexceptions" # ncnn.cmake 里面是关的,把它重新打开防止跟opencv2冲突,如果是重新编译ncnn的请自己尝试要开还是关 ) add_library(ScanJia-jni SHARED ScanJia_jni.cpp AngleNet.cpp BitmapUtils.cpp clipper.cpp CrnnNet.cpp DbNet.cpp DocDewarp.cpp DocLayout.cpp DocumentCorrection.cpp DocumentEdge.cpp LayoutUtils.cpp OCRDoc.cpp OcrLite.cpp OcrResultUtils.cpp OcrUtils.cpp parmas.cpp praxis.cpp TextDirection.cpp) target_link_libraries(ScanJia-jni ${OnnxRuntime_LIBS} ncnn ${OpenCV_LIBS} jnigraphics)
- 配置native-lib.cpp:
在Jni中调用CPP的代码:
extern "C" JNIEXPORT jstring JNICALL Java_com_dashu_scanjia_ScanJiaSim_OCR(JNIEnv *env,jobject, jobject image) {
int padding = 50; float boxScoreThresh = 0.6; float boxThresh = 0.3; float unClipRatio = 2.0; bool doAngle = true; bool mostAngle = true; int maxSideLen = 1024; cv::Mat imgRGBA, imgBGR, imgOut; bitmapToMat(env, image, imgRGBA); cv::cvtColor(imgRGBA, imgBGR, cv::COLOR_RGBA2BGR); int originMaxSide = (std::max)(imgBGR.cols, imgBGR.rows); int resize; if (maxSideLen <= 0 || maxSideLen > originMaxSide) {
resize = originMaxSide; } else {
resize = maxSideLen; } resize += 2*padding; cv::Rect paddingRect(padding, padding, imgBGR.cols, imgBGR.rows); cv::Mat paddingSrc = makePadding(imgBGR, padding); //按比例缩小图像,减少文字分割时间 ppocr::ScaleParam s = ppocr::getScaleParam(paddingSrc, resize);//例:按长或宽缩放 src.cols=不缩放,src.cols/2=长度缩小一半 ppocr::OcrResult ocrResult = ocrLite->detect(paddingSrc, paddingRect, s, boxScoreThresh, boxThresh, unClipRatio, doAngle, mostAngle); cv::cvtColor(ocrResult.boxImg, imgOut, cv::COLOR_BGR2RGBA); cv::resize(imgOut,imgOut,imgRGBA.size()); matToBitmap(env, imgOut, image); return env->NewStringUTF(ocrResult.strRes.c_str()); }
二、封装so库
上面大概演示了NDK项目是如何导入与调用C++代码的,但很多时候,C++的实现代码并不能都给别人,所要把.cpp文件封装成.so文件,只留api接口给用户调用。要封装成.so文件分步,一是指定so文件输出的目录,二是指定哪些.cpp文件封装成.so 。

- 指定SO输出目录
在CMakeLists.txt里面添加下面语句来指定生成的so输出的路径:
讯享网set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI})
- 指定生成so的.cpp文件
我这里有很多个cpp文件,可以选择全部导入,也可以选择导入要封装的.cpp文件。
add_library(ScanJia-jni SHARED ScanJia_jni.cpp AngleNet.cpp BitmapUtils.cpp clipper.cpp CrnnNet.cpp DbNet.cpp DocDewarp.cpp DocLayout.cpp DocumentCorrection.cpp DocumentEdge.cpp LayoutUtils.cpp OCRDoc.cpp OcrLite.cpp OcrResultUtils.cpp OcrUtils.cpp parmas.cpp praxis.cpp TextDirection.cpp)
- 编译生成.so
编译工程,编译完成之后可以在指定的地方找到的编译好的.so文件:

三、调用库
在CMakeLists.txt里面指定so文件路径,就可以不用依赖.cpp文件:
讯享网1.添加第三方库 add_library(ScanJia-lib SHARED IMPORTED ScanJia_jni.cpp) 2.添加库的路径 set_target_properties(ScanJia-lib PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI}/libScanJia-jni.so) target_link_libraries(ScanJia-jni ScanJia-lib ${OnnxRuntime_LIBS} ncnn ${OpenCV_LIBS} jnigraphics)
整体的CMakeLists.txt文件变化如下:
project(ScanJiaLib) cmake_minimum_required(VERSION 3.4.1) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fopenmp") set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fopenmp") if(DEFINED ANDROID_NDK_MAJOR AND ${ANDROID_NDK_MAJOR} GREATER 20) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -static-openmp") endif() 封装时用到,指定so库的输出路径 #set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI}) opencv 库 set(OpenCV_DIR "${CMAKE_SOURCE_DIR}/sdk/native/jni") find_package(OpenCV REQUIRED) if (OpenCV_FOUND) message(STATUS "OpenCV_LIBS: ${OpenCV_LIBS}") message(STATUS "OpenCV_INCLUDE_DIRS: ${OpenCV_INCLUDE_DIRS}") else () message(FATAL_ERROR "opencv Not Found!") endif (OpenCV_FOUND) include(${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime-shared/OnnxRuntimeWrapper.cmake) find_package(OnnxRuntime REQUIRED) if (OnnxRuntime_FOUND) message(STATUS "OnnxRuntime_LIBS: ${OnnxRuntime_LIBS}") message(STATUS "OnnxRuntime_INCLUDE_DIRS: ${OnnxRuntime_INCLUDE_DIRS}") else () message(FATAL_ERROR "onnxruntime Not Found!") endif (OnnxRuntime_FOUND) #ncnn库 set(ncnn_DIR ${CMAKE_SOURCE_DIR}/ncnn--android-vulkan/${ANDROID_ABI}/lib/cmake/ncnn) find_package(ncnn REQUIRED) set_target_properties( ncnn PROPERTIES INTERFACE_COMPILE_OPTIONS "-frtti;-fexceptions" # ncnn.cmake 里面是关的,把它重新打开防止跟opencv2冲突,如果是重新编译ncnn的请自己尝试要开还是关 ) 调用.so文件 1.添加第三方库 #add_library(ScanJia-lib SHARED IMPORTED ScanJia_jni.cpp) 2.添加库的路径 #set_target_properties(ScanJia-lib # PROPERTIES IMPORTED_LOCATION # ${PROJECT_SOURCE_DIR}/libs/${ANDROID_ABI}/libScanJia-jni.so) add_library(ScanJia-jni SHARED ScanJia_jni.cpp AngleNet.cpp BitmapUtils.cpp clipper.cpp CrnnNet.cpp DbNet.cpp DocDewarp.cpp DocLayout.cpp DocumentCorrection.cpp DocumentEdge.cpp LayoutUtils.cpp OCRDoc.cpp OcrLite.cpp OcrResultUtils.cpp OcrUtils.cpp parmas.cpp praxis.cpp TextDirection.cpp) target_link_libraries(ScanJia-jni ${OnnxRuntime_LIBS} ncnn ${OpenCV_LIBS} jnigraphics) 另外加的.cpp文件 #add_library(ScanJia-jni SHARED ScanJia_jni.cpp) 整体调用 #target_link_libraries(ScanJia-jni ScanJia-lib ${OnnxRuntime_LIBS} ncnn ${OpenCV_LIBS} jnigraphics)



版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/29543.html