2017-06-13 91 views
1

我有一個cv :: Mat的雙倍圖像,我已經截斷了0.0和4095.0之間。我想能夠轉換這個矩陣/創建一個新的矩陣,基於這個是12位的。 (保存0 - > 4095個整數值所需的最小int大小)。我只能得到原始緩衝區,但是我不確定矩陣內數據的格式。以OpenCV Mat <doube>並轉換爲12位值數組。

手動我可以執行以下操作:

cv::Mat new_matrix(/*type CV_8UC3, size (matrix.rows, matrix.cols/2)*/); 
for(int i = 0; i < matrix.rows; ++i){ 
    for(int j = 0; j < matrix.cols; ++j){ 
     std::uint16_t upper_half = static_cast<std::uint16_t>(matrix.at<double>(j*2,i)); 
     std::uint16_t lower_half = static_cast<std::uint16_t>(matrix.at<double>(j*2+1,i)); 
     std::uint8_t first_byte = static_cast<std::uint8_t>(upper_half>>4); 
     std::uint8_t second_byte = static_cast<std::uint8_t>(upper_half<<4) | static_cast<std::uint8_t>(lower_half <<12>> 12); 
     std::uint8_t third_byte = static_cast<std::uint8_t>(lower_half>>4); 

     new_matrix.at<cv::Vec3B>(j, i) = cv::Vec3b(first_byte, second_byte, third_byte); 
    } 
} 

其基本上壓縮兩個雙值以一個用於上半部分,一個用於下,提取三個字節出來的(12 + 12 = 24,24/8 = 3)轉換成3字節的矩陣。我不能確定,如果內存佈局將匹配出打包12位的但是(我有一個偶數的cols的,所以劃分的cols/2是不是一個問題),我不知道如何確保這種服從字節序。

I might even be able to use a custom data type,但我需要確保,如果說我做了一個聯盟結構的12位類型或某事的元素是不能填補。轉換後

注意,我不打算再使用OpenCV中的12位值,然後我需要提取原始值,他們得到發送到另一個單獨的進程。

回答

1

CV ::墊將數據存儲在8個單位,最小。這意味着您的12位值將被填充到矩陣內部,如Mat :: elemSize1()的返回值所示,該值位於字節數中。對於你需要做什麼,最好的辦法似乎是使用自定義的結構保持2個值(結構尺寸字節填充爲好),然後收拾一切都在一個std :: vector的<>。當你有一個奇數的樣本時,你將浪費在流數據上最差的12位填充。

有關包裝的說明:如果你使用類似下面,你需要扭轉位尺寸元素的順序,根據不同的機器,如果你需要從一個架構傳輸的字節到另一個。

#pragma pack(push, 1) 
struct PackedSamples { 
    char lowA; 
    char highA : 4; // NOTE: the declaration of bit sized fields order is inverse when 
    char lowB : 4; // going from BIG_ENDIAN to SMALL_ENDIAN and vice-versa 
    char highB; 
}; 

#pragma pack(pop) 

這裏是我用於測試字節順序的宏,我假設Windows在x86/x64上運行。 AMD是__BIG_ENDIAN。

#ifdef WIN32 
# ifndef __BYTE_ORDER 
# define __LITTLE_ENDIAN 1234 
# define __BIG_ENDIAN 4321 
# define __BYTE_ORDER __LITTLE_ENDIAN 
# endif 
#else 
# include <endian.h> 
#endif 

所以上面的聲明將成爲:

#pragma pack(push, 1) 
    struct PackedSamples { 
     char lowA; 
    #if __BYTE_ORDER == __LITTLE_ENDIAN 
     char highA : 4; 
     char lowB : 4; 
    #else 
     char lowB : 4; 
     char highA : 4; 
    #endif 
     char highB; 
    }; 

    #pragma pack(pop) 
+0

我可能會最終接受這個答案,但我不會需要實現這一點,直到後來,我將給予好評這個現在。 – snb

+0

爲什麼'struct PackedSamples {int A:12; int B:12};'?如果(目標)字節順序是big-endian,你不需要寫'{char highA; char highB:4; char lowA:4; char lowB; }'? – chtz