bitmap与mat互转方便opencv操作
Posted 西瓜6
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bitmap与mat互转方便opencv操作相关的知识,希望对你有一定的参考价值。
bitmap与mat互转方便opencv操作
前言
老实说接下来要说的有点复杂,甚至还有可能不够特别详细。所以哪里有不懂的,可以在这篇博客下留言,我也会及时回复留言和修改这篇博客。
开发工具是android studio,达到的效果是在java层中输入bitmap,在c++层里将bitmap转为mat,然后用opencv来进行图像处理,最后将处理好的mat再转为bitmap给到java层。
正文
首先说下需要有哪些文件,一个java文件,一个cpp文件,一个CMakeLists.txt。
cpp文件怎么写
这个cpp文件怎么写是个大难点,因为如果你本身会使用JNI调用c++代码,那么你应该只要看这一部分就好。代码我也是从别的地方复制来的,然后运行没有报错。
#include <jni.h>
#include <string>
#include <android/log.h>
#include <opencv2/opencv.hpp>
#include <android/bitmap.h>
#include <opencv2/imgproc.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/calib3d/calib3d.hpp>
#include <opencv2/imgproc/imgproc.hpp>
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<Mat>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 %d\\n", 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} )
结束语
亲测可用,然后哪里有报错改哪里就行。
嘿嘿,有帮助就点个赞和关注咯。感谢各位。
以上是关于bitmap与mat互转方便opencv操作的主要内容,如果未能解决你的问题,请参考以下文章