2014-10-16 97 views
1

我目前正在處理從保存爲16位灰度PNG的kinect傳感器檢索的深度圖像。目前我只是使用imread()函數和CV_LOAD_IMAGE_GRAYSCALE標誌加載這些圖像,並且一切正常。我這樣做的原因是因爲一些OpenCV函數依賴於輸入8位OpenCV如何在16位和8位之間進行imread轉換

下面是問題:下一步是直接使用由16位傳感器捕獲的深度幀。我雖然這將足以使用covertTo(dst, CV_8U, 1.0/256.0)來縮放和轉換值,但由於某種原因,生成的圖像與加載爲8位的圖像看起來非常不同。那麼,OpenCV如何將圖像加載爲8位時進行轉換。

這裏是我用於測試的image,這裏是一些代碼,顯示問題:

int main(int argc, char *argv[]){ 

    Mat depth8 = imread(argv[1], CV_LOAD_IMAGE_GRAYSCALE); 
    Mat depth16 = imread(argv[1], CV_LOAD_IMAGE_ANYDEPTH); 

    depth16.convertTo(depth16, CV_8U, 1.0/256.0); 

    Mat diff; 
    absdiff(depth8, depth16, diff); 

    //imshow("depth8", depth8*255.0/16.0); 
    //imshow("depth16", depth16*255.0/16.0); 
    imshow("diff", diff > 0); 
    waitKey(0); 

    return 0; 
} 

代碼的輸出可以發現here

如果您想知道爲什麼測試圖像太暗,這是因爲16位的最大值比kinect產生的值(可達4000左右)大得多。

另一件事:作爲8位加載的圖像似乎比轉換的好得多。如果你在兩行中發表評論,你可以看到我的意思。

再說一遍:OpenCV如何進行轉換?

在此先感謝。

+1

可能只是從16位值中獲取8個最高有效位。 – 2014-10-16 16:21:50

+0

是的,就是這樣。我測試了它,他們真的只是抓住了一點點。這很奇怪,因爲每當用戶想要在類型間轉換時,他們正在應用saturate_cast <>。在文檔中他們說他們正在這樣做「不僅僅是通過採取一些輸入來形成結果」。 – thomas 2014-10-16 17:08:07

回答

3
  1. imread函數最終會調用imread_(...)highgui/src/loadsave.cpp

  2. 將在imread_函數中確定正確的解碼器,並根據imread()中的第二個參數初始化矩陣mat

  3. mat傳遞給解碼器的readData()方法。在這種情況下,調用png解碼器。

  4. 根據mat的深度,可能會調用png解碼器中的png_set_strip_16highgui/src/grfmt_png.cpp)。

  5. png_set_strip_16()使libpng最終調用png_do_chop()。 (它只是丟棄低字節,參見libpng中的pngrtran.c