前言
OpenCV中保存圖片的函數在c++版本中變成了imwrite(),這應該是向matlab中圖像處理的的一些函數風格靠近吧。保存圖片這個功能還是很重要的,比如說在寫科研論文的時候需要把一些中間圖片給貼出來,這樣就可以在程序中間利用該函數保存圖片了。甚至還可以將這些保存的圖片供后續的matlab處理。本文就簡單介紹下OpenCV中imwrite()函數的用法。不過個人感覺這個函數功能還是不夠強大,使用時有很多限制。
開發環境:QtCreato2.5.1+OpenCV2.4.3
實驗基礎
本次實驗主要是測試imwrite()函數的2個功能:
1. 測試其是否能夠保存Mat圖像中截取的一部分圖像,比如說用Rect矩陣截取大的圖像中的一部分,由於此時兩者只是用了自己的文件頭,數據是共享的(沒有采用copyTo()函數或者clone()函數復制),所以這種測試想法很正常。
2. 測試imwrite()函數的第3個參數的使用。
在針對第1個測試時,是給定一張原圖,截取一部分,然后保存。針對第2個功能是采用OpenCV官網文件中的一個例子,創建一個alpha表,然后保存為png格式的圖片,壓縮參數自設定。
首先來看看imwrite()函數的具體用法。
bool imwrite(const string& filename, InputArray img, const vector<int>& params=vector<int>() )
該函數是把程序中的Mat類型的矩陣保存為圖像到指定位置。
參數filename為所需保存圖像的文件目錄和文件名。這里的文件名需要帶有圖像格式后綴的,目前OpenCV該函數只支持JPEG,PNG,PPM,PGM,PBM,TIFF等。並不是所有Mat類型都支持。
img參數為圖像數據來源,其類型為Mat。注意也不是所有格式的Mat型數據都能被使用保存為圖片,目前OpenCV主要只支持單通道和3通道的圖像,並且此時要求其深度為8bit和16bit無符號(即CV_16U)。所以其他一些數據類型是不支持的,比如說float型等。如果Mat類型數據的深度和通道數不滿足上面的要求,則需要使用convertTo()函數和cvtColor()函數來進行轉換。convertTo()函數負責轉換數據類型不同的Mat,即可以將類似float型的Mat轉換到imwrite()函數能夠接受的類型。而cvtColor()函數是負責轉換不同通道的Mat,因為該函數的第4個參數就可以設置目的Mat數據的通道數(只是我們一般沒有用到它,一般情況下這個函數是用來進行色彩空間轉換的)。另外也可以不用imwrite()函數來存圖片數據,可以直接用通用的XML IO接口函數將數據存在XML或者YXML中。
參數params是用來設置對應圖片格式的參數的,因為一般情況下這些圖片格式都是經過了壓縮的,這里就是設置這些壓縮參數來控制圖片的質量。該參數是一個vector<int>類型,里面分別存入paramId_1, paramValue_1, paramId_2, paramValue_2, ... 也就是說存入一對屬性值。如果不設置該參數的話,則程序會自動根據所保存的圖像格式采用一個默認的參數。
本實驗中還用到了下面這個函數。
template<...> _Tp saturate_cast(_Tp2 v)
將參數v轉換成模板中的類型,比如說:
uchar a = saturate_cast<uchar>(-100);
OpenCV知識點總結:
Rect的構造函數中不能重載3個參數,比如左上角點的坐標,寬和高這時候應該改成4個,左上角點的坐標直接分開為2個寫,對應着了點的x和y。
實驗結果
程序執行后工程文件夾中顯示如下:
說明截取圖像部分並保存是成功的。
原圖像和截取原圖中間1/4大小的圖像如下:
后台輸出如下:
說明此時也保存成功了。
生成的alpha表圖像顯示如下:
實驗代碼及注釋
main.cpp:
#include <iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace std; using namespace cv; Mat src; Mat image; string str = "./"; /*創建alpha表,整體偏紅色,左上角到右下角呈現從完全透明到完全不透明變化趨勢*/ void createAlphaMat(Mat &mat) { for (int i = 0; i < mat.rows; ++i) { for (int j = 0; j < mat.cols; ++j) { Vec4b& rgba = mat.at<Vec4b>(i, j); rgba[0] = UCHAR_MAX; //r分量一直最大,所以整體偏紅 rgba[1] = saturate_cast<uchar>((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX); rgba[2] = saturate_cast<uchar>((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX); rgba[3] = saturate_cast<uchar>(0.5 * (rgba[1] + rgba[2])); } } } int main() { /*采用默認參數進行圖片的保存*/ src = imread("test.jpg"); imwrite(str+"原圖.jpg", src); //c版本中的保存圖片為cvSaveImage()函數,c++版本中直接與matlab的相似,imwrite()函數。 imshow("src", src); Rect rect(src.cols/4, src.rows/4, src.cols/2, src.rows/2); image = src(rect); imwrite(str+"截取原圖中的一部分區域小圖.jpg", image); imshow("image", image); /*采用自己設置的參數來保存圖片*/ Mat mat(480, 640, CV_8UC4); createAlphaMat(mat); vector<int> compression_params; compression_params.push_back(CV_IMWRITE_PNG_COMPRESSION); compression_params.push_back(9); //png格式下,默認的參數為3. try { imwrite("alpha.png", mat, compression_params); } catch (runtime_error& ex) { fprintf(stderr, "Exception converting image to PNG format: %s\n", ex.what()); return 1; } fprintf(stdout, "Saved PNG file with alpha data.\n"); waitKey(0); return 0; }
實驗總結
Imwrite()函數可以保存截取出的圖像,但是這個函數使用時受限制太多,希望后面的版本對其進行加強。
參考資料