2017-03-06 45 views
0

私はAndroidで画像処理プロジェクトを構築しています。私はカメラを通してビットマップ画像をキャプチャし、JNIを介してopencv C++関数にフィードします。JNIでビットマップをOpencv :: Matに変換

まず、保存されたビットマップ画像(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++関数に送ります。ただし、検出された結果はまったく異なります。 JavaのビットマップをC++のopencv matにJNIを通して変換するときに、いくつかのエラーがあるはずです。下記の変換コードをご覧ください:

//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 

2つの "im"は異なるはずです。誰かが変換で間違っていることを教えてもらえますか?ありがとう。

+0

jintの長さは32ビットで、charは16であることに注意してください。 – mko

+0

"CV_8UC4"は間違っていますか? –

+0

いいえ、この1つ:(unsigned char *)cbuf – mko

答えて

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 *にキャストした後、あなたは意志あなたのデータを単に「散らす」。

関連する問題