2013-10-04 354 views
3

我有一個問題,將圖像數據從圖像採集卡中解析爲OpenCV Mat格式。我可以從我的EDT圖像採集卡中獲取圖像數據作爲無符號字符指針並將其傳遞給新創建的Mat,但我在這個過程中丟失了寶貴的數據,我不知道如何解決它。將unsigned char *圖像轉換爲OpenCV的問題Mat

我的相機是一個紅外相機,可輸出12位320x256拜耳圖像。我相當確信我使用EDT的API是正確的。使用EDT的軟件「pdvshow」,我可以按預期查看圖像數據,但是當我將來自EDT API的返回幀轉換爲OpenCV Mat並顯示它時,我會丟失大量數據。當Mat設置爲CV16UC1時,框架接近黑色,當Mat設置爲CV8UC1時,該框架顯示大部分數據,但顯得非常粗糙,有些斑點完全被吹掉。我知道圖像採集卡以兩個字節存儲每個12位像素,並且數據是MSB對齊的。 GetStride返回0

unsigned char *pdvImage; 
pdvImage = pdv_image(pdv_p); 

cv::Mat freshFrame; 
freshFrame = cv::Mat(GetHeight(), GetWidth(), CV_16UC1, pdvImage, GetStride()); //was CV_16UC1 but 8UC1 shows more data 

return freshFrame.clone(); 

回答

1

當您創建freshFrame作爲CV_16UC1墊,數據的12位是在最顯著位。縮放數據將解決產生的圖像顯得太黑的問題。因此,而不是

return freshFrame.clone(); 

你需要

return freshFrame * 16; 

您可能還需要檢查兩個字節的字節順序爲每個像素在pdvImage

關於CV_8UC1這是不行的

freshFrame = cv::Mat(GetHeight(), GetWidth(), CV_8UC1, pdvImage, GetStride()); 

因爲pdvImage前兩個字節組成圖像的第一像素的值,但成爲freshFrame兩個單獨的像素。但是,如果按上面的行創建freshFrame,則第一個字節將成爲freshFrame中第一個像素的值,第二個字節將成爲第二個像素的值,依此類推。顯然這是錯誤的。如果你真的需要一個CV_8UC1墊子,那麼創建一個CV_16UC1墊子然後轉換它可能是最簡單的。

1

我寫了繪製一個char *圖像,然後將其轉換爲OpenCV的墊代碼:

const int WIDTH = 800, HEIGHT = 600; 

uchar *data = new uchar[WIDTH * HEIGHT * 3]; 

for (int i = 0; i < WIDTH*HEIGHT*3;i+=3) 
{ 
    if (i < WIDTH*HEIGHT*3/2) 
    { 
     data[i + 0] = (uchar)0; 
     data[i + 1] = (uchar)0; 
     data[i + 2] = (uchar)255; 
    } 
    else 
    { 
     data[i + 0] = (uchar)255; 
     data[i + 1] = (uchar)0; 
     data[i + 2] = (uchar)0; 
    } 
} 

cout << "May God be pleased with you, amen!\n"; 

Mat colorfrm = Mat(HEIGHT, WIDTH, CV_8UC3); 
colorfrm.data = data; 

while (1) 
{ 
    imshow("Original Image", colorfrm); 

    ///////// 

    int c = cvWaitKey(30); 
    if (c == ' ') 
    { 
     break; 
    } 
    if (c == 'q' || c == 'Q' || c == 27) 
    { 
     return 0; 
    } 
} 

我希望這會有所幫助!