android中通过JNI读取Bitmap文件,并调用opencv进行处理

本文介绍如何在Android应用中通过JNI调用OpenCV处理Bitmap图像,包括创建Bitmap对象、定义JNI方法传递Bitmap、解析Bitmap内容及转换为OpenCV Mat对象等步骤。
📄 AI 智能文档扫描仪 -

基于OpenCV透视变换算法,提供文档自动扫描与矫正服务,支持边缘检测、歪斜拉直及去阴影增强,集成WebUI,纯算法零依赖版

在android中,通过JNI读取Bitmap文件并调用opencv进行处理,分为四步:1,activity中创建Bitmap对象;2,通过JNI定义native方法并传递Bitmap对象进去;,3,解析Bitmap对象;4,利用解析数据生成opencv的Mat对象,并进行相关处理。

1,activity中创建Bitmap对象

android支持几种Bitmap格式,RGBA_8888,RGB_565,RGBA_4444,A_8等等,格式不同存储方式就不同,在后面解析时的处理方法也自然不同。在activity中读入图像文件并创建Bitmap对象时,可以指定Bitmap的格式。为了后面更易于转换成Mat,我设定的格式是RGBA_8888。方法如下:

//指定图像的路径,这里是在sd卡中

String src_path =  Environment.getExternalStorageDirectory().getPath()+"/up.jpg";
String body_path = Environment.getExternalStorageDirectory().getPath()+"/down.jpg";

//读取sd卡中的图像,变为bitmap对象
File file1 = new File(src_path);
File file2 = new File(body_path);
        //若该文件存在
        if (file1.exists() && file2.exists()) {

//指定Bitmap的格式
        Options opt = new Options();
        opt.inPreferredConfig = Bitmap.Config.ARGB_8888;
        //读取文件并创建Bitmap对象
        Bitmap bmp1 = BitmapFactory.decodeFile(src_path,opt);
        Bitmap bmp2 = BitmapFactory.decodeFile(body_path,opt); 

}

2,通过JNI定义native方法并传递Bitmap对象进去

要把Bitmap作为native方法的参数传递进去,只要将其定义为Object类型即可,例如:

public  native int bodyDetect(Object bmp1,Object bmp2,double meanRatio,int[] target_rect);

前两个参数都是Bitmap对象,利用javah生成的头文件如下:

JNIEXPORT jint JNICALL Java_com_example_helloworld_BodyDetect_bodyDetect (JNIEnv *, jobject, jobject, jobject, jdouble, jintArray);

3,解析Bitmap对象

在jni的cpp文件中将传进来的Bitmap对象的内容解析出来,主要利用了android的两个函数:AndroidBitmap_getInfo(...),AndroidBitmap_lockPixels(..),AndroidBitmap_unlockPixels(...)。流程如下:

#ifndef LOGE
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"@",__VA_ARGS__)
#endif

JNIEXPORT jint JNICALL Java_com_example_helloworld_BodyDetect_bodyDetect
  (JNIEnv * env, jobject obj, jobject jbmp1, jobject jbmp2, jdouble jmeanRatio,jintArray jtarget_rect)
{
AndroidBitmapInfo bmp1info;
void* bmp1pixels;
AndroidBitmapInfo bmp2info;
void* bmp2pixels;
int height,width,ret,y,x;


//解析bitmap
if ((ret = AndroidBitmap_getInfo(env, jbmp1, &bmp1info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return -1;
}
if ((ret = AndroidBitmap_getInfo(env, jbmp2, &bmp2info)) < 0) {
LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret);
return -1;
}


if (bmp1info.format != ANDROID_BITMAP_FORMAT_RGBA_8888 || bmp1info.format != ANDROID_BITMAP_FORMAT_RGBA_8888) {
LOGE("Bitmap format is not RGBA_8888!");
return -1;
}


if ((ret = AndroidBitmap_lockPixels(env, jbmp1, &bmp1pixels)) < 0) {
LOGE("First Bitmap LockPixels Failed return=%d!", ret);
return -1;
}


if ((ret = AndroidBitmap_lockPixels(env, jbmp2, &bmp2pixels)) < 0) {
LOGE("Second Bitmap LockPixels Failed return=%d!", ret);
return -1;
}

。。。

AndroidBitmap_unlockPixels(env, jbmp1);
AndroidBitmap_unlockPixels(env, jbmp2);

}

4,利用解析数据生成opencv的Mat对象,并进行相关处理。

RGBA_8888格式的Bitmap,一个像素占32位,分别是A:8bit,R:8bit;G:8bit;B:8bit。对应到opencv的Mat对象,有个一个Mat的构造函数,结果接受外部数据数组并生Mat对象,这将大大方便转换过程,不用逐像素的操作了。如下:

。。。

//将bitmap转成灰度图像
height = bmp1info.height;
width = bmp1info.width;
Mat src(height,width,CV_8UC4,bmp1pixels);
Mat body(height,width,CV_8UC4,bmp2pixels);
if(!(src.data &&body.data)){
LOGE("bitmap failed convert to Mat return=%d!", ret);
return -1;
}
//转换为灰度图像
cvtColor(src,src,CV_RGBA2GRAY);
cvtColor(body,body,CV_RGBA2GRAY);

。。。

 

这里由Bitmap对象转换成Mat这么容易,是因为RGBA_8888格式的存储方式正好与Mat的CV_8UC4对应。如果是其他格式的Bitmap转成Mat,则要麻烦多了。可以参考几个帖子:

http://blog.csdn.net/youngc527/article/details/25424729

http://bbs.csdn.net/topics/390773967

http://blog.csdn.net/wwj_748/article/details/8206299

待调好了这种方式,再作补充。


您可能感兴趣的与本文相关的镜像

📄 AI 智能文档扫描仪 -

📄 AI 智能文档扫描仪 -

图片编辑
Python
PyTorch

基于OpenCV透视变换算法,提供文档自动扫描与矫正服务,支持边缘检测、歪斜拉直及去阴影增强,集成WebUI,纯算法零依赖版

评论 9
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值