OpenCv NDK 银行卡/身份证号识别(2) Bitmap和Mat相互转化

我们都知道在我们android程序中一个图片的表达是使用的Bitamp来存储的,而在Opencv中图片的存储是Mat矩阵的形式。所以如果我们想把我们android的图片传给opencv,就要先把bitmap转成Mat类型,所以我们先来了解以下Mat是个什么东西。

1.Mat简单介绍

一个图片都是有很多像素点组成的,所以mat矩阵就是保存我们这个图片的像素点的集合。每个像素点又都是又RGBA颜色组成,所以在Opencv中Mat分为单通道和多通道存储,这个就很好理解了,比如我们有一个灰色图片Mat在存储是就是单通道的,还有我们的图片是彩色的BGR这个在Mat中就是三通道,BGRA四通到等等。这个大家可以自行去百度了解。

OpenCv NDK 银行卡/身份证号识别(2) Bitmap和Mat相互转化_第1张图片

在我们把Bitmap转成Mat之前我们要知道一个对应关系,由上面介绍可以Mat矩阵保存图片时候是分不同的通道的。我们知道android中bitmap在创建的时候也是有类型的比如:RGBA_8888,所以对应关系如下:

  RGBA_8888 -> CV_8UC4  四颜色通道
  RGB_565   -> CV_8UC2  三颜色通道
  GRAY      ->  CV_8UC1 单通道(黑白)

所以我们在做Bitmap转Mat时候要根据Bitamp的类型来转化使用不同的通道,不然会出错。因为不同的通道代表的mat开辟的内存不一样,比如我们Mat矩阵中的一个像素点A:
如果我们的图片是       单通道 A = 白色/黑色(0--255)大小;
                                    三颜色通道 A = R(0--255)G(0--255)B(0--255);
                                    四颜色通道 A = R(0--255)G(0--255)B(0--255)A(0--255);
由此可见通道不一样,创建Mat的大小是不一样的,所以要一一对应。

2.Bitmap和Mat相互转化

通过上述的分析我们简单的了解了Mat,那么下面就上代码:

Bitmap转Mat:

int BitmapUtils::Bitmap2mat(JNIEnv *env, jobject bitmap, Mat *mat) {
    void *addrPtr;
    AndroidBitmap_lockPixels(env, bitmap, &addrPtr);

    AndroidBitmapInfo bitmapInfo;

    AndroidBitmap_getInfo(env, bitmap, &bitmapInfo);

    Mat createM(bitmapInfo.height, bitmapInfo.width, CV_8UC4);

    if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGBA_8888) {
        Mat tep(bitmapInfo.height, bitmapInfo.width, CV_8UC4, addrPtr);
        tep.copyTo(createM);
    } else if (bitmapInfo.format == ANDROID_BITMAP_FORMAT_RGB_565) {
        Mat tep(bitmapInfo.height, bitmapInfo.width, CV_8UC2, addrPtr);
        cvtColor(tep, createM, COLOR_BGR5652RGBA);
    }
    createM.copyTo(*mat);
    createM.release();
    AndroidBitmap_unlockPixels(env, bitmap);

    return 0;
}

里面有一些android ndk 提供的类 AndroidBitmapInfo 我们还记得上一篇中我们在CMakeList中添加了一个库 ‘jnigraphics’这个就是我们android底层的C++代码,我们用的Bitamp就是用这个库转化到native层然后进行处理的。也是我们android源码的一部分。

Mat转Bitmap:

int BitmapUtils::Mat2Bitmap(JNIEnv *env, jobject bitmap, Mat &mat) {

    AndroidBitmapInfo info;
    AndroidBitmap_getInfo(env, bitmap, &info);

    void *pixels;
    //锁定 bitmap
    AndroidBitmap_lockPixels(env, bitmap, &pixels);
    __android_log_print(ANDROID_LOG_ERROR, "Mat2Bitmap-RECT-", "%d", mat.cols);
    if (info.format == ANDROID_BITMAP_FORMAT_RGBA_8888) { //bitmap
        Mat tmp(info.height, info.width, CV_8UC4, pixels);
        if (mat.type() == CV_8UC1) {
            cvtColor(mat, tmp, COLOR_GRAY2RGBA);
        } else if (mat.type() == CV_8UC2) {
            cvtColor(mat, tmp, COLOR_BGR5652BGRA);
        } else if (mat.type() == CV_8UC4) {
            mat.copyTo(tmp);
        }
    } else if (info.format == ANDROID_BITMAP_FORMAT_RGB_565) {
        Mat tmp(info.height, info.width, CV_8UC2, pixels);
        if (mat.type() == CV_8UC1) {
            cvtColor(mat, tmp, COLOR_GRAY2BGR565);
        } else if (mat.type() == CV_8UC2) {
            mat.copyTo(tmp);
        } else if (mat.type() == CV_8UC4) {
            cvtColor(mat, tmp, COLOR_RGBA2BGR565);
        }
    }
    return 0;
}

简单了解图像在Opencv中储存的形式和怎么把android的图片转化成OPencv能处理的图片,从bitmap转化成Mat之后,接下来就是对图像数据的操作。

你可能感兴趣的:(Android,NDK/C/C++开发实战,OpenCV,NDK图像数字识别)