2017-03-06 64 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++函數。但是,檢測結果完全不同。我認爲在通過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」應該不同。有人能告訴我轉換中有什麼問題嗎?謝謝。

+0

請注意,jint是32位長,而字符只是16. – mko

+0

所以你的意思是「CV_8UC4」不正確? –

+0

不可以,這一個:(無符號字符*)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 *後,你會只是「分散」你的數據。