一 影像存盤容器
學習影像處理首先要學會如何操作矩陣資訊,在OpenCV中提供了一個Mat類用于存盤矩陣資料,
Mat類用來保存矩陣型別的資料資訊,包括向量,矩陣,灰度或彩色影像等資料,Mat類分為矩陣頭和指向存盤資料的矩陣指標兩部分,其中矩陣頭中包含矩陣的尺寸、存盤方法、地址和參考次數,矩陣頭的大小是一個常數,不會隨著矩陣尺寸的大小二改變,在絕大多數情況下,矩陣頭大小遠小于矩陣中資料量的大小,因此影像復制和傳遞程序中的主要開銷是存放矩陣資料,
1.創建Mat類
cv::Mat a; //創建一個名為a的矩陣頭
a = cv::imread("test.jpg") //向a中賦值影像資料,矩陣指標指向像素資料
cv::Mat b = a //復制矩陣頭
上述代碼,首先創建了名為a的矩陣頭,之后讀入一張影像并將中的矩陣指標指向該圖的像素資料,最后將a矩陣頭中的內容復制到b矩陣頭中,雖然a、b有各自的矩陣頭,但是矩陣指標所指向的是同一矩陣資料,所以通過任意矩陣頭修改矩陣中的資料時,另一個矩陣頭指向的資料也會發生改變,但是當洗掉變數a時,b變數并不會指向一個空資料,只用當兩個變數同時洗掉時,才會釋放矩陣資料,因為矩陣頭中參考次數標記了參考某個矩陣的次數,只有當矩陣的參考次數為0的時候才會釋放矩陣資料,
1.1宣告一個指定型別的Mat類
cv::Mat A = Mat_<double>(3,3); //創建一個3*3的矩陣用于存放double資料型別
Mat可以存盤的資料型別包括double,float,uchar,unsigned char,以及自定義模板,
1.2通過OpenCV資料型別創建Mat類
| 資料型別 | 具體型別 | 取值范圍 |
| CV_8U | 8位無符號整數 | 0~255 |
| CV_8S | 8位符號整數 | -128~127 |
| CV_16U | 16位無符號整數 | 0~65535 |
| CV_16S | 16位符號整數 | -32768~32767 |
| CV_32S | 32位符號整數 | -2147483~2147483647 |
| CV_32F | 32位浮點小數 | 略 |
| CV_64F | 64位浮點小數 | 略 |
cv::Mat a(640,480,CV_8UC3) //創建一個640*480 的三通道矩陣用于存放彩色影像
cv::Mat a(3,3,CV_8UC1) //創建一個3*3的8位無符號整數的單通道矩陣
cv::Mat a(3,3,CV_8U) //創建單通道矩陣,c1標識可以省略
注意:雖然在64位編譯器里,uchar和CV_8U都表示8位無符號整數,但是兩者有著嚴格的定義,CV_8U只能用于Mat類內部構建方法,如果用Mat_<CV_8U>(3,3)和Mat a(3,3,CV_8U),就會提示創建錯誤,
2.Mat類構造與賦值
2.1 Mat類的構造
(1)利用默認建構式
cv::Mat::Mat();
這種構造方式不需要輸入任何的引數,在后續給變數賦值的時候會自動判斷矩陣的型別大小,實作靈活的存盤,常用于存盤讀取的影像資料和某個函式的運算輸出結果,
(2)根據輸入矩陣尺寸和型別構造
cv::Mat::Mat( int rows,
int cols,
int type,
)
//rows:構造矩陣的行數
//cols:構造矩陣的列數
//type:矩陣中存盤的資料型別
(3)用Size()結構構造Mat類
cv::Mat::Mat(Size size(),
int type
)
//size: 二維陣列變數尺寸,通過Size(cols,rows)來進行賦值,注意列在前,行在后
//type:略
(4)利用已有矩陣構造Mat實體
cv::Mat()::Mat(const Mat &m)
//m:以構建完成的Mat類矩陣變數
希望復制兩個一模一樣的Mat類而批次之間不會影響,那么可以使用m=a.clone()
(5)創建已有Mat類的子類
cv::Mat::Mat(const Mat &m,
const Range &rowRange,
const Range &colRange = Range::all()
)
//m: 已經構建完成的Mat類矩陣資料
//rowRange:在以有矩陣中需要截取的行數范圍,是一個Range變數,例如Range(2,5)表示從第二行, //到第五行
//colRange:截取列的范圍
//這種方式主要用于在原圖中截圖使用,不過需要注意的是,通過這種方式構造的Mat類與已有Mat類享有共同的資料,
2.Mat類的賦值
(1)在構造時賦值
cv::Mat::Mat(int rows,
int cols,
int type,
const Scalar &s
)
//rows:略
//cols:略
//type:略
//s: 給矩陣中沒個像素賦值的引數變數
//實體:
cv::Mat::Mat(2, 2, CV_8UC3, CV::Scalar(0,0,255))
(2)列舉法賦值
cv::Mat::Mat(cv::Mat_<int>(3,3)<<1, 2, 3, 4, 5, 6, 7, 8, 9);
(3)利用回圈賦值
cv::Mat c = cv::Mat_(3, 3); //定義一個3*3的矩陣
for (int i = 0; i < c.rows; i++)
{
for (int j = 0; j < c.cols; j++)
{
c.at<int>(i, j) = i + j;
{
}
(4)利用類方法賦值
cv::Mat a = cv::Mat::eye(3, 3, CV_8UC1);
cv::Mat b = (cv::Mat_<int>(1, 3) <<1, 2, 3);
cv::Mat c = cv::Mat::diag(b);
cv::Mat d = cv::Mat::ones(3, 3, CV_8UC1);
cv::Mat e = cv::Mat::zeros(4, 2, CV_8UC3);
//eye:創建一個單位矩陣,如果行和列不相等,在(1,1),(2,2),等主對角線出為1
//diag:創建對角矩陣,其引數必須是Mat型別的一維變數,用來存放對角元素的數值
//ones:創建一個全為1的矩陣
//zeros:創建一個全為0的矩陣
(5)利用陣列進行賦值
float a[8] = {5, 6, 7, 8, 1, 2, 3, 4, };
cv::Mat b = cv::Mat(2, 2, CV_32FC2, a);
CV::Mat c = cv::Mat(2, 4, CV_32FC1, a);
//當矩陣中的元素數目大于陣列中的資料時,將用-1.0737418e+08填充給矩陣;當矩陣中元素的數目小于陣列中的資料時,將矩陣賦值完成后,陣列中剩余資料將不再賦值,
3.Mat類支持的運算
Mat支持加減乘除的運算,在對影像進行卷積運算時,需要兩個矩陣進行乘法運算,OpenCV提供了兩個Mat類矩陣的乘法運算,而且定義了兩個矩陣的內積和對應位的乘法運算,
cv::Mat() j,m;
double k;
j = c*d;
k = a.dot(b);
m = a.mul(b);
4.Mat類元素的讀取
| 屬性 | 作用 |
| cols | 矩陣的列數 |
| rows | 矩陣的行數 |
| step | 以位元組為單位的矩陣有效寬度 |
| elemSize() | 每個元素的位元組數 |
| total() | 矩陣中元素的個數 |
| channels() | 矩陣的通道數 |
(1)通過at方法讀取Mat類矩陣中的元素
//讀取單通道矩陣元素
cv::Mat a = (cv::Mat_<uchar>(3, 3) <<1, 2, 3, 4, 5, 6, 7, 8, 9);
int value = (int)a.at<uchar>(0, 0);
//讀取多通道矩陣元素
cv::Mat b(3, 4, CV_8UC3, CV::Scalar(0, 0, 1));
cv::Vec3b vc3 = b.at<cv::Vec3b>(0, 0);
int first = (int)vc3.val[0];
int second = (int)vc3.val[1];
int third = (int)vc3.val[2];
//在使用多通道變數型別是,同樣需要注意at方法中資料變數型別與矩陣的變數型別相對應,
//并且cv::Vec3b型別在輸入每個通道資料是需要將其變數型別強制轉化成int型別,
針對三通道矩陣,定義了cv::Vec3b,cv::Vec3s,cv::Vec3w,cv::Vec3d,cv::Vec3f,cv::Vec3i,b是uchar型別的縮寫,s是short型別的縮寫,w是ushort型別的縮寫,d是double型別的縮寫,f是float型別的縮寫, i是int型別的縮寫,
(2)通過指標ptr讀取Mat類矩陣中的元素
Mat類矩陣中每一行中的每個元素都是挨著存放的,所以給出了通道指標ptr讀取Mat類矩陣元素,
cv::Mat b(3, 4, CV_8UC3, cv::Scalar(0, 0, 1));
for (int i = 0; i < b.rows; i++)
{
uchar* ptr = b.ptr<uchar>(i);
for(int j = 0; j < b.cols*b.channels(); j++)
{
cout << (int)ptr[j] <<endl;
}
}
(3)通過迭代器訪問Mat類矩陣中的元素
cv::MatIterator_<uchar> it = a.begin<uchar>();
cv::MatIterator_<uchar> it_end = a.end<uchar>();
for(int i = 0; it ! = it_end; it++)
{
cout << (int)(*it) <<"";
if((++i%a.cols) == 0)
{
cout << endl;
}
}
Mat類的迭代器變數型別是cv::MatIterator_<>,在定義時同樣需要在尖括號中宣告資料的變數型別,Mat類迭代器的起始是Mat.begin<>(),借宿是Mat.end<>(),與其他迭代器用法相同,通過“++”運算實作指標位置向下迭代,資料的讀取方式是先讀取第一個元素的每一個通道,之后再讀取第二個元素的每一個通道,直到最后一個元素的最后一個通道,
(4)通過矩陣元素的地址定位方式訪問元素
(int)(*(b.data + b.step[0] * row + b.step[1] * col + channel));
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/299596.html
標籤:AI
