1、Mat結構
1.1、Mat數據
Mat本質上是由兩個數據部分組成的類:
矩陣頭:包含信息有矩陣的大小,用於存儲的方法,矩陣存儲的地址等
數據矩陣指針:指向包含了像素值的矩陣。
矩陣頭部的大小是恆定的,矩陣本身的大小因圖像的不同而不同,通常是較大的數量級。
在程序中傳遞圖像並在有些時候創建圖像副本需要花費很大的代價生成圖像矩陣本身,而不是圖像的頭部。為了解決這一問題 OpenCV 使用引用計數系統。其思想是Mat的每個對象具有其自己的頭,但可能他們通過讓他們矩陣指針指向同一地址的兩個實例之間共享該矩陣。此外,拷貝運算符將只能復制矩陣頭部,也還將復制指針到大型矩陣,但不是矩陣本身。如果需要復制矩陣的本身,要使用 clone() 或 copyTo() 函數。
其中 Mat 類中有一些基本屬性:
cols :矩陣列數
rows:矩陣行數
channels:通道數
type:數據類型
total:矩陣總元素數
data:指向矩陣數據塊的指針
1.2、Mat數據類型定義
其中 Mat 排列方式如下:
CV_[
位數][
帶符號與否][
類型前綴]C[
通道數
]
帶符號與否:S為符號整型,U為無符號整型,F為浮點型
例如CV_8UC3
多通道數據類型的定義如下:
#define CV_8U 0 #define CV_8S 1 #define CV_16U 2 #define CV_16S 3 #define CV_32S 4 #define CV_32F 5 #define CV_64F 6 #define CV_USRTYPE1 7 #define CV_MAT_DEPTH_MASK (CV_DEPTH_MAX - 1) #define CV_MAT_DEPTH(flags) ((flags) & CV_MAT_DEPTH_MASK) #define CV_MAKETYPE(depth,cn) (CV_MAT_DEPTH(depth) + (((cn)-1) << CV_CN_SHIFT)) #define CV_MAKE_TYPE CV_MAKETYPE #define CV_8UC1 CV_MAKETYPE(CV_8U,1) #define CV_8UC2 CV_MAKETYPE(CV_8U,2) #define CV_8UC3 CV_MAKETYPE(CV_8U,3) #define CV_8UC4 CV_MAKETYPE(CV_8U,4)
2、Mat應用
2.1 構造函數
(1) Mat::Mat() (2) Mat::Mat(int rows, int cols, int type) (3) Mat::Mat(Size size, int type) (4) Mat::Mat(int rows, int cols, int type, const Scalar& s) (5) Mat::Mat(Size size, int type, const Scalar& s) (6) Mat::Mat(const Mat& m) (7) Mat::Mat(int rows, int cols, int type, void* data, size_t step = AUTO_STEP) (8) Mat::Mat(Size size, int type, void* data, size_t step = AUTO_STEP) (9) Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange) (10) Mat::Mat(const Mat& m, const Rect& roi) (11) Mat::Mat(const CvMat* m, bool copyData = false) (12) Mat::Mat(const IplImage* img, bool copyData = false) (13) template<typename T, int n>explicit Mat::Mat(const Vec<T, n>& vec, bool copyData = true) (14) template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData = true) (15) template explicit Mat::Mat(const vector& vec, bool copyData = false) (16) Mat::Mat(const MatExpr& expr) (17) Mat::Mat(int ndims, const int* sizes, int type) (18) Mat::Mat(int ndims, const int* sizes, int type, const Scalar& s) (19) Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps = 0)
2.2 創建Mat類型數據
1)使用Mat構造函數創建
Mat mat = Mat(2, 3, CV_8UC1); cout << "rows="<<mat.rows << ",cols=" << mat.cols << endl; cout << mat << endl;
輸出:
rows=2,cols=3 [205, 205, 205; 205, 205, 205] |
創建三通道矩陣Mat mat(2, 3, CV_8UC3);輸出如下。
rows=2,cols=3 [205, 205, 205, 205, 205, 205, 205, 205, 205; 205, 205, 205, 205, 205, 205, 205, 205, 205] |
創建三通道矩陣Mat mat(2, 3, CV_8UC3, Scalar(0,0,255)
rows=2,cols=3 [ 0, 0, 255, 0, 0, 255, 0, 0, 255; 0, 0, 255, 0, 0, 255, 0, 0, 255] |
2)使用Create函數進行初始化
Mat M; M.create(2, 3, CV_8UC1); cout << "M = " << endl << " " << M << endl << endl;
輸出如下。
M = [205, 205, 205; 205, 205, 205] |
3)使用標准函數進行特定矩陣初始化
Mat M; M = Mat::eye(4, 4, CV_8U); Mat M1 = Mat::ones(4, 4, CV_8U);
Mat M2= Mat::zeros(4, 4, CV_8U); cout << "M = " << endl << " " << M << endl << endl; cout << "M1 = " << endl << " " << M1 << endl << endl; cout << "M2 = " << endl << " " << M2 << endl << endl;
輸出如下。
M = [ 1, 0, 0, 0; 0, 1, 0, 0; 0, 0, 1, 0; 0, 0, 0, 1] M1 = [ 1, 1, 1, 1; 1, 1, 1, 1; 1, 1, 1, 1; 1, 1, 1, 1] M2 = [ 0, 0, 0, 0; 0, 0, 0, 0; 0, 0, 0, 0; 0, 0, 0, 0] |
輸出Mat矩陣可以格式化不同的形式,如下所示。
cout <<"M = "<< endl <<" "<< format( M, Formatter::FMT_PYTHON) << endl << endl;
M =
[[ 1, 0, 0, 0],
[ 0, 1, 0, 0],
[ 0, 0, 1, 0],
[ 0, 0, 0, 1]]
2.3 Mat操作像素
1. at定位符訪問
2、指針訪問
3.迭代器iterator訪問
1)Mat::at
Mat數據結構,操作灰度圖像像素點:
int gray_value = (int) image.at<uchar>(i , j) ;
操作彩色圖像像素點:
int color_value = (int) image.at<Vec3b>(i , j) [k];
其中:
gray_value中存放灰度值,image是讀入的圖像,i表示行,j表示列;
color_value中存放彩色像素值,image是讀入的圖像,i表示行,j表示列,k表示通道,即R、G、B,取值范圍為2、1、0.
template<typename T> T& Mat::at(int i)const
template<typename T> const T&Mat::at(int i) const
template<typename T> T& Mat::at(int i,int j)
template<typename T> const T&Mat::at(int i, int j) const
template<typename T> T& Mat::at(Pointpt)
template<typename T> const T&Mat::at(Point pt) const
template<typename T> T& Mat::at(int i,int j, int k)
template<typename T> const T&Mat::at(int i, int j, int k) const
template<typename T> T& Mat::at(constint* idx)
template<typename T> const T&Mat::at(const int* idx) const
參數
i –索引 0 維度
j – 1 維度的索引
k – 沿 2 維度的索引
pt – Point(j,i) 作為指定元素的位置。
idx – Mat::dims 數組的索引
int main() { Mat M= Mat::eye(100, 200, CV_8U); for(int i=0; i<M.rows; i++) for (int j = 0; j < M.cols; j++) { M.at<uchar>(i, j) = j / 10 * 10; } imshow("pic1", M); waitKey(0); }
2)指針訪問
Mat mat = Mat(10, 15, CV_8UC1); cout << "rows=" << mat.rows << ",cols=" << mat.cols << endl; for (int i = 0; i < mat.rows; i++) { uchar* row = mat.ptr<uchar>(i); // 行指針 for (int j = 0; j < mat.cols; j++) // 遍歷每一行 { row[j] = (uchar)((j / 5) * 10); } } cout << "M = " << endl << " " << format(mat, Formatter::FMT_PYTHON) << endl << endl; waitKey(0);
輸出如下。
rows=10,cols=15 |
3)迭代器iterator訪問
Mat M = Mat(100, 150, CV_8UC3); cout << "rows=" << M.rows << ",cols=" << M.cols << endl; Mat_<Vec3b>::iterator it = M.begin<Vec3b>();//初始位置的迭代器 Mat_<Vec3b>::iterator itend = M.end<Vec3b>();//終止位置的迭代器 for (; it != itend; it++) { //處理BGR三個通道 (*it)[0] = 182;//B (*it)[1] = 194;//G (*it)[2] = 154;//R } imshow("pic1", M);
使用下面配色表實驗:
配色1: RGB(182,194,154)
配色2:RGB(229,131, 8)
2.4 其他數據結構
1)點的表示:Point
Point p1 = { 2,3 }; Point p2 = Point2i(3, 4); Point2f p3; p3.x = 1.1; p3.y = 1.2; cout << "p1=" << p1 << endl; cout << "p2=" << p2 << endl; cout << "p3=" << p3 << endl; waitKey(0);
輸出為:
p1=[2, 3]
p2=[3, 4]
p3=[1.1, 1.2]
2)顏色表示:Scalar
Scalar(r, g, b)分別表示紅綠藍顏色。
3)尺寸的表示:Size
Size a = Size(5, 6); cout <<"a.width=" << a.width << ":a.height=" << a.height;
輸出為:
a.width=5:a.height=6
4)矩形的表示:Rect
Rect rect = Rect(100, 50, 10, 20); // 參數:x、y、width、height cout << rect.area() << endl; //返回rect的面積 200 cout << rect.size() << endl; //返回rect的尺寸 [10 × 20] cout << rect.tl() << endl; //返回rect的左上頂點的坐標 [100, 50] cout << rect.br() << endl; //返回rect的右下頂點的坐標 [110, 70] cout << rect.width << endl; //返回rect的寬度 10 cout << rect.height << endl; //返回rect的高度 20 cout << rect.contains(Point(101, 51) ) << endl; //返回布爾變量,判斷是否包含Point點
輸出為:
200 [10 x 20] [100, 50] [110, 70] 10 20 1 |
3、參考文獻
1、Mat - The Basic Image Container
https://docs.opencv.org/master/d6/d6d/tutorial_mat_the_basic_image_container.html
2、cv::Mat Class Reference
https://docs.opencv.org/3.1.0/d3/d63/classcv_1_1Mat.html
3、OpenCV Mat 常用的基礎知識
https://blog.csdn.net/Librarvl/article/details/89892352
4、OpenCV Mat類詳解和用法
https://blog.csdn.net/Mason_Mao/article/details/82254285
5、《OpenCV3 編程入門》 , 電子工業出版社,毛星雨著
尊重原創技術文章,轉載請注明。