赞
踩
OpenCv官网,这边下载的是4.6.0
复制目录opencv-4.6.0-android-sdk\OpenCV-android-sdk\sdk\native\jni的include文件夹,和opencv-4.6.0-android-sdk\OpenCV-android-sdk\sdk\native\libs\armeabi-v7a目录对应的cpu架构类型.项目没有对应目录,手动创建一下.
可以参考Android NDK项目CMakeLists.txt配置导入第三方库
# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. cmake_minimum_required(VERSION 3.18.1) # Declares and names the project. project("mnnmyh") aux_source_directory(. SRC_LIST) # 当前文件夹下的所有文件,不包含子文件夹 add_library( # Sets the name of the library. mnnmyh # Sets the library as a shared library. SHARED # Provides a relative path to your source file(s). #native-lib.cpp) ${SRC_LIST}) #opencv include_directories(${CMAKE_SOURCE_DIR}/opencv/include/) add_library(libopencv_java4 SHARED IMPORTED) set_target_properties( libopencv_java4 PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libopencv_java4.so) find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log) target_link_libraries( # Specifies the target library. mnnmyh # Links the target library to the log library # included in the NDK. ${log-lib} #jnigraphics库可以用来从android.bitmap.Graphics类 访问C / C ++中的位图缓冲区 jnigraphics libopencv_java4 )
参考github OpenCV ,实现图片灰度转换
先写一个bitmap转mat工具类
utils.hpp
// // Created by moyihen on 2022/8/17. // #include "opencv2/core.hpp" #include "opencv2/imgproc.hpp" #ifdef __ANDROID__ #include <android/bitmap.h> #include "android/log.h" #define TAG "org.opencv.android.Utils" #define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG, __VA_ARGS__) #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__) #define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__) #define LOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG, __VA_ARGS__) #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG, __VA_ARGS__) using namespace cv; void BitmapToMat(JNIEnv *env, jobject bitmap, Mat &dst, jboolean needUnPremultiplyAlpha) { AndroidBitmapInfo info; void *pixels = 0; try { CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0); 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); dst.create(info.height, info.width, CV_8UC4); if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) { LOGD("nBitmapToMat: RGBA_8888 -> CV_8UC4"); Mat tmp(info.height, info.width, CV_8UC4, pixels); if (needUnPremultiplyAlpha) cvtColor(tmp, dst, COLOR_mRGBA2RGBA); else tmp.copyTo(dst); } else { // info.format == ANDROID_BITMAP_FORMAT_RGB_565 LOGD("nBitmapToMat: RGB_565 -> CV_8UC4"); Mat tmp(info.height, info.width, CV_8UC2, pixels); cvtColor(tmp, dst, COLOR_BGR5652RGBA); } AndroidBitmap_unlockPixels(env, bitmap); return; } catch (const cv::Exception &e) { AndroidBitmap_unlockPixels(env, bitmap); LOGE("nBitmapToMat caught cv::Exception: %s", e.what()); jclass je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, e.what()); return; } catch (...) { AndroidBitmap_unlockPixels(env, bitmap); LOGE("nBitmapToMat caught unknown exception (...)"); jclass je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}"); return; } } void MatToBitmap(JNIEnv *env, Mat &src, jobject bitmap, jboolean needPremultiplyAlpha) { AndroidBitmapInfo info; void *pixels = 0; try { LOGD("nMatToBitmap"); CV_Assert(AndroidBitmap_getInfo(env, bitmap, &info) >= 0); CV_Assert(info.format == ANDROID_BITMAP_FORMAT_RGBA_8888 || info.format == ANDROID_BITMAP_FORMAT_RGB_565); CV_Assert(src.dims == 2 && info.height == (uint32_t) src.rows && info.width == (uint32_t) src.cols); CV_Assert(src.type() == CV_8UC1 || src.type() == CV_8UC3 || src.type() == CV_8UC4); CV_Assert(AndroidBitmap_lockPixels(env, bitmap, &pixels) >= 0); CV_Assert(pixels); if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) { Mat tmp(info.height, info.width, CV_8UC4, pixels); if (src.type() == CV_8UC1) { LOGD("nMatToBitmap: CV_8UC1 -> RGBA_8888"); cvtColor(src, tmp, COLOR_GRAY2RGBA); } else if (src.type() == CV_8UC3) { LOGD("nMatToBitmap: CV_8UC3 -> RGBA_8888"); cvtColor(src, tmp, COLOR_RGB2RGBA); } else if (src.type() == CV_8UC4) { LOGD("nMatToBitmap: CV_8UC4 -> RGBA_8888"); if (needPremultiplyAlpha) cvtColor(src, tmp, COLOR_RGBA2mRGBA); else src.copyTo(tmp); } } else { // info.format == ANDROID_BITMAP_FORMAT_RGB_565 Mat tmp(info.height, info.width, CV_8UC2, pixels); if (src.type() == CV_8UC1) { LOGD("nMatToBitmap: CV_8UC1 -> RGB_565"); cvtColor(src, tmp, COLOR_GRAY2BGR565); } else if (src.type() == CV_8UC3) { LOGD("nMatToBitmap: CV_8UC3 -> RGB_565"); cvtColor(src, tmp, COLOR_RGB2BGR565); } else if (src.type() == CV_8UC4) { LOGD("nMatToBitmap: CV_8UC4 -> RGB_565"); cvtColor(src, tmp, COLOR_RGBA2BGR565); } } AndroidBitmap_unlockPixels(env, bitmap); return; } catch (const cv::Exception &e) { AndroidBitmap_unlockPixels(env, bitmap); LOGE("nMatToBitmap caught cv::Exception: %s", e.what()); jclass je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, e.what()); return; } catch (...) { AndroidBitmap_unlockPixels(env, bitmap); LOGE("nMatToBitmap caught unknown exception (...)"); jclass je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}"); return; } } #endif //__ANDROID__
nativ方法实现
native-lib.cpp
#include <jni.h> #include <string> #include "utils.hpp" extern "C" JNIEXPORT jstring JNICALL Java_com_moyihen_mnnmyh_JniBitmapUtil_stringFromJNI(JNIEnv *env, jclass clazz) { std::string hello = "Hello from C++"; return env->NewStringUTF(hello.c_str()); } extern "C" JNIEXPORT void JNICALL Java_com_moyihen_mnnmyh_JniBitmapUtil_coverImg2Gray(JNIEnv *env, jclass clazz, jobject bitmap) { //源图像 Mat src; //将Bitmap转换为Mat BitmapToMat(env,bitmap,src, JNI_FALSE); //转换的灰度图 Mat gray_image; cvtColor(src, gray_image, COLOR_BGR2GRAY ); //将Mat转换为Bitmap MatToBitmap(env,gray_image,bitmap, JNI_FALSE); //释放Mat src.release(); gray_image.release(); }
import android.graphics.Bitmap; public class JniBitmapUtil { // Used to load the 'mnnmyh' library on application startup. static { System.loadLibrary("mnnmyh"); } /** * A native method that is implemented by the 'mnnmyh' native library, * which is packaged with this application. */ public static native String stringFromJNI(); public static native void coverImg2Gray(Bitmap bitmap); }
调用
mCvBinding.button.setOnClickListener(v -> {
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.hzw);
JniBitmapUtil.coverImg2Gray(bitmap);
mCvBinding.img2.setImageBitmap(bitmap);
});
效果
注意:调试的时候出现几个问题,可以参考下
1. dlopen failed: library “libc++_shared.so” not found
需在在app的build.gradle配置arguments “-DANDROID_STL=c++_shared”
defaultConfig {
externalNativeBuild {
cmake {
cppFlags '-std=c++11'
arguments "-DANDROID_STL=c++_shared"
}
}
}
2.error: undefined symbol: AndroidBitmap_getInfo
需要在CMakeLists.txt的target_link_libraries 加上jnigraphics
target_link_libraries( # Specifies the target library.
mnnmyh
# Links the target library to the log library
# included in the NDK.
${log-lib}
#jnigraphics库可以用来从android.bitmap.Graphics类 访问C / C ++中的位图缓冲区
jnigraphics
libopencv_java4
)
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。