老实说接下来要说的有点复杂,甚至还有可能不够特别详细。所以哪里有不懂的,可以在这篇博客下留言,我也会及时回复留言和修改这篇博客。
开发工具是android studio,达到的效果是在java层中输入bitmap,在c++层里将bitmap转为mat,然后用opencv来进行图像处理,最后将处理好的mat再转为bitmap给到java层。
首先说下需要有哪些文件,一个java文件,一个cpp文件,一个CMakeLists.txt。
cpp文件怎么写这个cpp文件怎么写是个大难点,因为如果你本身会使用JNI调用c++代码,那么你应该只要看这一部分就好。代码我也是从别的地方复制来的,然后运行没有报错。
#include#include #include #include #include #include #include #include #include using namespace cv; #undef LOG_TAG #define LOG_TAG "xigua6---[native]: " #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , LOG_TAG, __VA_ARGS__) void BitmapToMat2(JNIEnv *env, jobject& bitmap, Mat& mat, jboolean needUnPremultiplyAlpha) { AndroidBitmapInfo info; void *pixels = 0; Mat &dst = mat; try { //LOGD("nBitmapToMat"); 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 catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); if (!je) je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, e.what()); return; } catch (...) { AndroidBitmap_unlockPixels(env, bitmap); //LOGE("nBitmapToMat catched unknown exception (...)"); jclass je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, "Unknown exception in JNI code {nBitmapToMat}"); return; } } void BitmapToMat(JNIEnv *env, jobject& bitmap, Mat& mat) { BitmapToMat2(env, bitmap, mat, false); } void MatToBitmap2 (JNIEnv *env, Mat& mat, jobject& bitmap, jboolean needPremultiplyAlpha) { AndroidBitmapInfo info; void *pixels = 0; Mat &src = mat; 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 catched cv::Exception: %s", e.what()); jclass je = env->FindClass("org/opencv/core/CvException"); if (!je) je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, e.what()); return; } catch (...) { AndroidBitmap_unlockPixels(env, bitmap); //LOGE("nMatToBitmap catched unknown exception (...)"); jclass je = env->FindClass("java/lang/Exception"); env->ThrowNew(je, "Unknown exception in JNI code {nMatToBitmap}"); return; } } void MatToBitmap(JNIEnv *env, Mat& mat, jobject& bitmap) { MatToBitmap2(env, mat, bitmap, false); } extern "C" JNIEXPORT void JNICALL Java_xxx_xxx_xxx_antiAliasing(JNIEnv *env, jobject jobj, jobject jsrcBitmap1, jobject jsrcBitmap2 ){ LOGD("start"); Mat mat_image_src1,mat_image_src2; BitmapToMat(env,jsrcBitmap1,mat_image_src1);//(224结果)图片转化成mat LOGD("bitmap2mat small finish"); Mat img_alpha1,img_alpha2; std::vector mv1,mv2; split(mat_image_src1, mv1); LOGD("split small finish"); img_alpha1=mv1[3]; cv::resize(img_alpha1, img_alpha2, cv::Size(1920, 1080),INTER_CUBIC); LOGD("resize finish"); cv::threshold(img_alpha2, img_alpha2, 200, 255, THRESH_BINARY); LOGD("threshold finish"); cv::blur(img_alpha2, img_alpha2, Size(7,7)); LOGD("Blur finish"); //merge Mat mat_image_dst2; LOGD("channels %dn", img_alpha2.channels()); mv2.push_back(img_alpha2); mv2.push_back(img_alpha2); mv2.push_back(img_alpha2); mv2.push_back(img_alpha2); LOGD("m2 finish"); cv::merge(mv2, mat_image_dst2); LOGD("merge finish"); MatToBitmap(env,mat_image_dst2,jsrcBitmap2);//mat转成化图片 LOGD("mat2bitmap large finish"); LOGD("finish"); }
其中xxx是路径哈,这个是我随便写的一个bitmap_1转mat,然后用opencv对这个mat做一个简单的resize和滤波,最后再将这个mat转为bitmap_2。
java文件与CMakeLists.txt怎么写java一定要加的是三句
第一句
static {
System.loadLibrary("native-lib");
}
这里的native-lib是上面cpp的名字(native-lib.cpp),你的的cpp文件如果是xxx.cpp,那么这里面就是System.loadLibrary(“xxx”);
第二句
public native void antiAliasing(Bitmap bitmap1,Bitmap bitmap2);
也就是声明这个函数
第三句
antiAliasing(rgbframe224_224,rgbframe1920_1080);
也就是使用这个函数
而在CMakeLists.txt则是根据情况自己改,我把我的CMakeLists.txt粘出来,也可以照着参考着写一下哈。
# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
cmake_minimum_required(VERSION 3.4.1)
# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
add_library(libopencv_world SHARED importED)
add_library(libtbb SHARED importED)
add_library(libopencv_img_hash SHARED importED)
add_library( # Specifies the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp )
# Specifies a path to native header files.
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/include/)
include_directories(${CMAKE_SOURCE_DIR}/src/main/cpp/)
set_target_properties(libopencv_world PROPERTIES importED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_world.so)
set_target_properties(libtbb PROPERTIES importED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libtbb.so)
set_target_properties(libopencv_img_hash PROPERTIES importED_LOCATION
${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libopencv_img_hash.so)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
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 )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
libopencv_world
libtbb
libopencv_img_hash
jnigraphics
# links the target library to the log library
# included in the NDK.
${log-lib} )
结束语
亲测可用,然后哪里有报错改哪里就行。
嘿嘿,有帮助就点个赞和关注咯。感谢各位。



