想了多種方法解決這個問題,還是百度的力量大。
在很多應用中,經常會直接把圖片的二進制數據進行交換,比如說利用 socket 通信傳送圖片二進制數據,或者直接用內存數據庫(例如 Redis)來傳遞圖片二進制數據。
這個時候,當你的應用程序讀到內存裏的二進制圖片數據時,怎麼樣直接轉爲 OpenCV 可以使用的圖片格式呢,答案是用 cv::imdecode 這個函數。
即先構造一個 char 字符串序列的 vector,用來存儲圖片的二進制數據,然後再轉爲 cv::Mat 成爲可以被 cv::imdecode 使用的數據格式,然後直接類型轉換爲 IplImage 數據格式。
同樣,如果你需要把 IplImage 或 cv::Mat 壓縮並寫到一段內存塊裏時,就需要使用 cv::imencode 這個函數,使用方法類似。
具體的實現代碼參考:
string fname = "D:/image.jpg";
//! 以二進制流方式讀取圖片到內存
FILE* pFile = fopen(fname.c_str(), "rb");
fseek(pFile, 0, SEEK_END);
long lSize = ftell(pFile);
rewind(pFile);
char* pData = new char[lSize];
fread(pData, sizeof(char), lSize, pFile);
fclose(pFile);
//! 解碼內存數據,變成cv::Mat數據
cv::Mat img_decode;
vector<uchar> data;
for (int i = 0; i < lSize; ++i){
data.push_back(pData[i]);
}
img_decode = cv::imdecode(data, CV_LOAD_IMAGE_COLOR);
cv::flip(img_decode, img_decode, -1);
img_decode.channels();
//! 將cv::Mat數據編碼成數據流
vector<unsigned char> img_encode;
cv::imencode(".jpg", img_decode, img_encode);
unsigned char *encode_data = new unsigned char[lSize];
for (int i = 0; i<lSize; i++){
encode_data[i] = img_encode[i];
}
如果需要解碼的圖像格式特殊,如unit16的深度圖,請在調用imdecode時選擇CV_LOAD_IMAGE_UNCHANGED
Specific color type of the loaded image:
CV_LOAD_IMAGE_COLOR the loaded image is forced to be a 3-channel color image
CV_LOAD_IMAGE_GRAYSCALE the loaded image is forced to be grayscale
CV_LOAD_IMAGE_UNCHANGED the loaded image will be loaded as is.