OpenCV2:Mat

OpenCV2:Mat

1.Mat基礎

在計算機內存中,數字圖像是已矩陣的形式保存的。OpenCV2中,數據結構Mat是保存圖像像素信息的矩陣,它主要包含兩部分:矩陣頭和一個指向像素數據的矩陣指針。
矩陣頭主要包含,矩陣尺寸、存儲方法、存儲地址和引用次數等。
矩陣頭的大小是一個常數,不會隨着圖像的大小而改變,但是保存圖像像素數據的矩陣則會隨着圖像的大小而改變,通常數據量會很大,比矩陣頭大幾個數量級。這樣,在圖像複製和傳遞過程中,主要的開銷是由存放圖像像素的矩陣而引起的。因此,OpenCV使用了引用次數,當進行圖像複製和傳遞時,不再複製整個Mat數據,而只是複製矩陣頭和指向像素矩陣的指針。例如:
1
2
3
cv::Mat a ;//創建矩陣頭
a = cv::imread(“f:\psb.jpg”);//讀入圖像
cv::Mat b = a ;//複製 
上面的a,b有各自的矩陣頭,但是其矩陣指針指向同一個矩陣,也就是其中任何一個改變了矩陣數據都會影響另外一個。
那麼,多個Mat共用一個矩陣數據,最後誰來釋放矩陣數據呢?
這就是引用計數的作用,當Mat對象每被複制一次時,就會將引用計數加1,而每銷燬一個Mat對象(共用同一個矩陣數據)時引用計數會被減1,當引用計數爲0時,矩陣數據會被清理。

上圖是Mat對象a,b共用一個矩陣,故其引用計數refcount爲2.
但是有些時候仍然會需要複製矩陣數據本身(不只是矩陣頭和矩陣指針),這時候可以使用clone 和copyTo方法。
cv::Mat c = a.clone();
cv::Mat d ;
a.copyTo(d);
上面代碼中的c,d各自擁有自己的矩陣,改變自己的矩陣數據不會相互影響。
在使用Mat中,需要記住:
OpenCV中的內存分配是自動完成的(不是特別指定的話)
使用OpenCV的C++ 接口時不需要考慮內存釋放問題
Mat的賦值運算和拷貝構造函數只會拷貝矩陣頭,仍然共同同一個矩陣
如果要複製矩陣數據,可以使用clone和copyTo函數
2.Mat存儲方法

Mat中矩陣的每個元素可以使用不同的數據類型,最小的數據類型是char,佔用一個字節或者8位,可以是有符號的(0到255)或者是無符號的(-127到127)。在RGB顏色空間中,使用三個char類型可以表示1600萬中顏色,但在圖像處理的過程中有可能會使用到float或者double來表示圖像的像素。
Mat的創建

構造函數

cv::Mat img(2,2,CV_8UC3,cv::Scalar(0,0,255));
上述代碼創建了一個2行2列的矩陣,矩陣元素使用8位無符號char類型保存,具有3通道,每個像素的初始值是(0,0,255)
構造函數的前兩個參數指定了矩陣的行和列
第三個參數指定矩陣元素的數據類型以及通道數,其指定規則如下:
CV_[The number of bits per item][Signed or Unsigned][TypePrefix]C[The channel number]
四部分分別指定:元素的大小,是有符號還是無符號,數據類型以及通道數
最後一個參數,Scalar是short型的vector,提供矩陣的初始化。
Create方法

該方法不能爲矩陣設置初始值,只是在改變尺寸時爲矩陣數據重新分配內存。使用方法:
img.create(4,4,CV_8UC(2));
創建了一個4行4列有2個通道的矩陣
MATLAB形式的初始化

cv::Mat e = cv::Mat::eye(4,4,CV_64F);
cv::Mat z = cv::Mat::ones(2,2,CV_32F);
cv::Mat o = cv::Mat::zeros(3,3,CV_8UC1);
Mat e是4行4列的對角矩陣
Mat z是2行2列的單位矩陣
Mat o是3行3列的零矩陣
小矩陣的初始化

對於小矩陣可以使用逗號分割的初始化函數
Mat c =(Mat_(3,3)<<1,2,3,0,-1,0,4,5,6);
在對圖像進行模板運算時,定義模板使用這種方法是很方便的。
3.Mat的輸入輸出

使用imread函數,向Mat對象中寫入一個圖像。

a = cv::imread(“f:\psb.jpg”);//讀入圖像
imread的原型如下
cv::Mat imread(const string& filename,int flags=1)
filename指定要讀取圖像的位置
flags指定圖像的顏色空間
flags > 0 3通道的彩色圖像
flags = 0 灰度圖像
flags < 0 不作改變
也可以有以下的枚舉值
CV_LOAD_IMAGE_ANYDEPTH、CV_LOAD_IMAGE_COLOR、CV_LOAD_IMAGE_GRAYSCALE

使用imwrite函數,將Mat對象保存到指定的文件中。

imwrite的函數原型如下:
bool imwrite(const string& filename,InputArray img,constvector& params=vector())
filename,指定的文件
img 要保存的Mat對象
params 用來指定圖像的保存編碼方式。
使用filename的擴展名來指定圖像的保存格式(.jpg .png .bmp),對於不同的圖像保存類型,params是不同的值
JPEG,params用來指定圖像的質量(0到100),默認的是95. CV_IMWRITE_JPEG_QUALITY
PNG,params用來指定圖像的壓縮級別(0到9),壓縮級別越高圖像佔用的空間越小,保存圖像所用的時間越久。默認值是3. CV_IMWRITE_PNG_COMPRESSION
PPM,PGM,PBM,params是一個標記(0或者1),默認的是1.CV_IMWRITE_PXM_BINARY
imwrite只能保存8位(或者是16位無符號(CV_16UC)的PNG,JPEG200或者TIFF圖像)單通道或者三通道的圖像,如果要保存的不是這樣的圖片,可以使用convertTo或者cvtColor來進行轉變。
下面代碼展示瞭如果使用imwrite向文件中寫入一個4通道的png圖像
複製代碼
void createAlphaMat(Mat &mat)
{
for(int i = 0 ; i < mat.rows ; i ++) {
for(int j = 0 ; j < mat.cols ; j ++) {
Vec4b &rgba = mat.at(i,j);
rgba[0] = UCHAR_MAX ;
rgba[1] = saturate_cast((float (mat.cols - j)) / ((float)mat.cols) * UCHAR_MAX);
rgba[2] = saturate_cast((float (mat.rows - i)) / ((float)mat.rows) * UCHAR_MAX);
rgba[3] = saturate_cast(0.5 * (rgba[1] + rgba[2]));
}
}
}
int main()
{
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);

imwrite("alpha.png",mat,compression_params);

return 0;

}
複製代碼

4.Mat的顯示

OpenCV提供了用以窗口的形式顯示圖片的方法,代碼如下:
Mat img = imread(“f:\psb.jpg”);
const string name =”Hu”;
namedWindow(name);
imshow(name,img);
waitKey();

轉自:http://www.cnblogs.com/wangguchangqing/p/3841271.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章