【问题标题】:Converting bitmap to Opencv::Mat in JNI在 JNI 中将位图转换为 Opencv::Mat
【发布时间】:2017-03-06 10:48:24
【问题描述】:

我正在 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”应该是不同的。有人可以告诉我转换中有什么问题吗?谢谢。

【问题讨论】:

  • 请注意,jint 的长度为 32 位,而 char 的长度仅为 16。
  • 所以你的意思是“CV_8UC4”不正确?
  • 不,这个:(unsigned char *) cbuf
  • 我应该把它改成什么?谢谢。

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


【解决方案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 * 后,您将简单地“分散”数据。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-10-09
    • 2012-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-12
    相关资源
    最近更新 更多