opencv中imdecode函数

最近遇到一个问题,由于刚刚接触opencv,花了很多时间才解决。

问题是:
在android中有一些图片需要处理,处于性能和以后移植的考虑,决定将图片处理的部分用C来写,在安卓中通过JNI调用本地C中函数。安卓中将bitmap中的数据放到byte数组中,然后将byte数组传到C函数,C函数将byte数组恢复成Mat对象,以便使用opencv提供的一些函数。


//native 方法
public native int[] extractCode(byte[] img, int w, int h);


// 安卓中call native方法的代码片段
ByteArrayOutputStream streamimg = new ByteArrayOutputStream();
mybitmap.compress(Bitmap.CompressFormat.PNG, 100, streamimg);
byte[] img = streamimg.toByteArray();
int w = mybitmap.getWidth();
int h = mybitmap.getHeight();
int[] code = extractCode(img, w, h);    // call native method
// C代码
extern "C"
JNIEXPORT jintArray JNICALL
Java_com_fudan_encodeproject_decode_DecodeActivity_extractCode(JNIEnv *env, jobject instance,
jbyteArray img_, jint w, jint h) {
    jbyte *img = env->GetByteArrayElements(img_, NULL);
    // 企图通过这一步将byte数组转化成Mat对象,但是失败了
    Mat mimg(h, w, CV_8UC4, (unsigned char *)img);

    //直到加上这一句才成功 mimg = imdecode(mimg,CV_LOAD_IMAGE_COLOR);

    // 将原图返回
    jintArray code =  env->NewIntArray(w*h);
    jint *_data = new jint[mimg.total()];
    for (int i = 0; i < mimg.total(); i++) {
        char b = mimg.data[mimg.channels() * i];
        char g = mimg.data[mimg.channels() * i + 1];
        char r = mimg.data[mimg.channels() * i + 2];
        _data[i] = (((jint) 0xFF << 24) & 0xFF000000) + (((jint) r << 16) & 0x00FF0000) +
                   (((jint) g << 8) & 0x0000FF00) + ((jint) b & 0x000000FF);
    }
    env->SetIntArrayRegion(code, 0, mimg.total(), _data);
    env->ReleaseByteArrayElements(img_, img, 0);
    delete[]_data;
    return code;
}

执行完这个代码的时候,返回的图像并不是图像。于是我在stackoverflow上翻了好久,有个回答说应该加上 mimg = imdecode(mimg,CV_LOAD_IMAGE_COLOR);

很纳闷啊,为什么加上这一句就行了呢?

官方对imdecode函数的解释是:

/** @brief Reads an image from a buffer in memory.
The function imdecode reads an image from the specified buffer in the memory. If the buffer is too short or contains invalid data, the function returns an empty matrix ( Mat::data==NULL ).

See cv::imread for the list of supported formats and flags description.

@note In the case of color images, the decoded images will have the channels stored in B G R order.
@param buf Input array or vector of bytes.
@param flags The same flags as in cv::imread, see cv::ImreadModes.
*/
CV_EXPORTS_W Mat imdecode( InputArray buf, int flags );

也就是从内存中读取图片,如果内存中的数据太短或者不是合法的数据就返回一个空的矩阵。

我的猜测如下:
opencv使用BGR颜色空间,所有用opencv自带的方法load的图片都是BGR的,而且没有方法检测当前图片使用的是什么颜色空间。但是通过构造函数创建的Mat对象不是BGR的,所以在后续的操作就出问题了,但是imdecode函数可以将这个Mat对象转成BGR。
不知道怎么验证这个猜测,以后找到真正原因了再来更新吧。

你可能感兴趣的:(图像处理)