我們有很多方式可以從現實生活中得到圖片,數碼相機,掃描儀,或者我們幾乎人手有一部的手機。然而,當生活中的圖在數字設備上存儲的時候,一幅圖片被分成了很多很多的像素點,像素點就像拼圖的時候的碎片,一個個碎片來構成一副圖。而每個像素點都是由一個0-255的數字值來表示。在openCV中,一個圖片被很多像素點表示,這些表示像素點的值構成了一個矩陣。
上面的圖中,由表示像素點的值構成了矩陣,在openCV中,Mat(矩陣)是表示圖片的基本。
Mat由兩部分組成,一個是matrixheader,裡面存儲了一些信息,比如矩陣的大小,矩陣的存儲地址等;另外一個是矩陣,裡面包含了圖片的每一個像素值。
明白了Mat有兩部分組成後,能夠更好的理解Mat的賦值。看下面的一段代碼
#include<iostream> #include <opencv2/core/core.hpp> #include <opencv2/highgui/highgui.hpp> using namespace cv; int main() { Mat A, C; // 聲明其實只是創建了header部分 A = imread("zh.png",CV_LOAD_IMAGE_COLOR); // 這裡,A的matrix部分指向了一個矩陣 Mat B(A); // 使用構造方法賦值,其實只有header部分復制了, //但是matrix復制的是地址空間,指向的是同一片區域 C = A; // 同理,header部分復制了,但是matrix指向同一片區域 //A = A * 0; //只是改變了A,但是三幅圖都變了 imshow("A", A); //顯示的三幅圖片都是同一片區域 imshow("B", B); imshow("C", C); waitKey(); return 0; }
上面的A,B,C的header只是值相同,但是每一個Mat都有自己的header,但是matrix不一樣,他們不僅僅值相同,並且指向相同的地址空間。
現在你可能會疑惑,如果三個Mat的matrix都是同一片地址空間,那麼當它不再需要的時候,由誰來清除它。其實由最後一個使用它的那個Mat來清除,這裡面涉及的引用計數問題,和C++的引用計數應該是相似的。
如果我們需要一個和原來矩陣值一樣,但是原來Mat的改變不會影響新的Mat。解決這個,openCV提供了clone() 和copyTo() 這兩個函數。
Mat F = A.clone(); Mat G; A. copyTo(G);
上面的G和F,現在的值和A一樣,但是A的改變不會影響到他們。
就是如何存儲像素值,最簡單的方式是用灰度矩陣來存儲,前提是我們的圖片是黑白的時候,當然還有一些其它的圖片存儲方式,比如常見的RGB。
可以使用imwrite()將圖片寫出,也可以使用<<操作符。看下面的一段程序
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255)); std::cout << "M = " << std::endl<<""<< M << std::endl << std::endl; system("pause");//讓程序不閃退
Mat的構造函數,前兩個參數(這裡都是2)指定Mat的大小,行與列數。
定義“CV_8UC3”的格式一般是這樣的
CV_[The number of bits per item][Signed orUnsigned][Type Prefix]C[The channel number]
例如,CV_8UC3意思是我們用8 bitunsigned值表示單個數值,每個像素有3個數值來形成3個channel。
使用create()函數創建。
Mat M; M.create(4, 4, CV_8UC(2)); //參數的含義前面已經介紹了 cout << "M = " << endl<< ""<< M << endl << endl;
返回欄目頁:http://www.bianceng.cn/Programming/cplus/
Matlab風格,使用zeros(),ones(),eye(),
Mat E = Mat::eye(4, 4, CV_64F); cout << "E = " << endl<<""<< E << endl << endl; Mat O = Mat::ones(2, 2, CV_32F); cout << "O = " << endl<<""<< O << endl << endl; Mat Z = Mat::zeros(3, 3, CV_8UC1); cout << "Z = " << endl<< ""<< Z << endl << endl;
小矩陣,可以用這種方式初始化:
Mat C = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0); cout << "C = " << endl<< ""<< C << endl << endl;
可以使用randu()函數,隨機化一個矩陣,需要給定一個隨機的上下界
Mat R = Mat(3, 2, CV_8UC3); randu(R, Scalar::all(0),Scalar::all(255)); //0至255的值 cout << "R = " << endl<< ""<< R << endl << endl;
作者:csdn博客 鐘桓