在JNI中将位图转换为Opencv :: Mat

时间:2017-03-06 10:48:24

标签: android c++ opencv bitmap java-native-interface

我正在Android中构建一个图像处理项目。我通过相机捕获位图图片,并通过JNI将其提供给opencv C ++函数。

首先,我使用保存的位图图片(PNG格式)测试我的opencv c ++函数,并且它成功了。

  // in Android, save bitmap
  Bitmap bmp = YUV_420_888_toRGB(img,img.getWidth(),img.getHeight());
  try {
                    FileOutputStream fos = new FileOutputStream(pictureFile);
                    bmp.compress(Bitmap.CompressFormat.PNG, 100, fos);
                    fos.flush();
                    fos.close();
                    Log.e(TAG,"saved successfully.)");

                } catch (FileNotFoundException e) {
                    Log.d(TAG, "File not found: " + e.getMessage());
                } catch (IOException e) {
                    Log.d(TAG, "Error accessing file: " + e.getMessage());
                }

  // in opencv c++ function
  Mat im = imread("/Users/Jun/Downloads/20170227/P9/1488167433596_frame.PNG");

  // processing im

然后我将每个捕获的位图图片提供给相同的opencv c ++函数。但是,检测结果完全不同。我认为通过JNI将Java中的位图转换为C ++中的opencv mat时必定存在一些错误。请在下面找到转换代码:

   //Java side:
   public static int[] detector(Bitmap bitmap) {
    int w = bitmap.getWidth();
    int h = bitmap.getHeight();
    int []pixels = new int[w*h];
    bitmap.getPixels(pixels,0,w,0,0,w,h);

   return detect(pixels,w,h);

}

private static native int[] detect(int pixels[],int w,int h);


  // c++ side:
  JNIEXPORT jintArray JNICALL     Java_com_example_jun_helloworld_JNIUtils_detect(JNIEnv *env, jclass cls, jintArray buf, jint w, jint h) {
jint* cbuf = env->GetIntArrayElements(buf, false);
if (cbuf == NULL) {
    return NULL;
}
Mat im(h, w, CV_8UC4, (unsigned char *) cbuf);

// processing im

两个" im" s应该是不同的。有人能告诉我转换中的错误吗?感谢。

1 个答案:

答案 0 :(得分:1)

在代码中,将int指针转换为char指针。因此,您将更改代码处理数据的方式。

看看这里:

#include <stdio.h>

int main() {

    // what you have in the code is array of ints
    int iarray[5] = {1, 2, 3, 4, 5};
    int *iarray_ptr = iarray;

    // and you cast int pointer to char pointer
    char *carray_ptr = (char *) iarray_ptr;

    // so, you simply skip some values because of
    // pointer aritmetics; your data are shifted
    for(int i=0;i<5;i++) {
        printf("int: %p, char %p\n", iarray_ptr + i, carray_ptr + i);
    }

    // you can always do something like this
    char carray2[5];
    for(int p=0;p<5;p++) {
        // you can loose precision here!
        carray2[p] = (char) iarray[p];
    }

    // and then, you can simply pass &carray2 to
    // to your code
}

如果你运行代码,你可以清楚地看到指针算术的区别:

./pointer
int: 0x7fff51d859f0, char 0x7fff51d859f0
int: 0x7fff51d859f4, char 0x7fff51d859f1
int: 0x7fff51d859f8, char 0x7fff51d859f2
int: 0x7fff51d859fc, char 0x7fff51d859f3
int: 0x7fff51d85a00, char 0x7fff51d859f4

在转换为char *之后,您只需“分散”您的数据。