Mat常用成员属性
- data 是指向矩阵数据的uchar类指针,用*解引用后再强转为int可以读到第一个像素数据。
- dims 矩阵的维度,例如5*6矩阵是二维矩阵,则dims=2,三维矩阵dims=3。
- rows 矩阵的行数。
- cols 矩阵的列数。
- size 矩阵的大小,返回一个向量,二维矩阵即为 行数 x 列数。
Mat常用成员方法
channels()
矩阵元素拥有的通道数,例如常见的彩色图像,每一个像素由RGB三部分组成,则image.channels() = 3
。type()
表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。depth()
矩阵中元素的一个通道的数据类型,这个值和type是相关的。例如 type为 CV_16SC2,一个2通道的16位的有符号整数。那么,depth则是CV_16S。depth也是一系列的预定义值,
常用的构造函数有:
● Mat::Mat()
无参数构造方法;
● Mat::Mat(int rows, int cols, int type)
创建行数为 rows,列数为 col,类型为 type 的图像;
● Mat::Mat(Size size, int type)
创建大小为 size,类型为 type 的图像;
● Mat::Mat(int rows, int cols, int type, const Scalar& s)
创建行数为 rows,列数为 col,类型为 type 的图像,并将所有元素初始化为值 s;
● Mat::Mat(Size size, int type, const Scalar& s)
创建大小为 size,类型为 type 的图像,并将所有元素初始化为值 s;
● Mat::Mat(const Mat& m)
将 m 赋值给新创建的对象,此处不会对图像数据进行复制,m 和新对象共用图像数据;
● Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)
创建行数为 rows,列数为 col,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step指定。
● Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)
创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step 指定。
● Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据;
● Mat::Mat(const Mat& m, const Rect& roi)
创建的新图像为 m 的一部分,具体的范围 roi 指定,此构造函数也不进行图像数据的复制操作,新图像与 m 共用图像数据。
● 这些构造函数中,很多都涉及到类型type
。type可以是CV_8UC1,CV_16SC1,…,CV_64FC4 等。里面的 8U 表示 8 位无符号整数,16S 表示 16 位有符号整数,64F表示 64 位浮点数(即 double 类型);C 后面的数表示通道数,例如 C1 表示一个通道的图像,C4 表示 4 个通道的图像,以此类推。如果你需要更多的通道数,需要用宏 CV_8UC(n),
create()
函数
Mat类的create()函数可以重新分配内存空间:
Mat M(2,2, CV_8UC3);//构造函数创建图像
M.create(3,2, CV_8UC2);//释放内存重新创建图像
使用 create()函数无法设置图像像素的初始值
零矩阵等Matlab风格函数zeros()
,ones()
,eye()
等
OpenCV 2 中提供了 Matlab 风格的函数,如 zeros(),ones()和 eyes()。可以方便指定图像大小和类型等,使用方法如下:
Mat Z = Mat::zeros(2,3, CV_8UC1);
cout << "Z = " << endl << " " << Z << endl;
Mat O = Mat::ones(2, 3, CV_32F);
cout << "O = " << endl << " " << O << endl;
Mat E = Mat::eye(2, 3, CV_64F);
cout << "E = " << endl << " " << E << endl;
读写像素函数at()
at()可以用来读取像素值或者写入像素值,使用方法如下:
uchar value = grayim.at<uchar>(i,j);//读出第 i 行第 j 列像素值
grayim.at<uchar>(i,j)=128; //将第 i 行第 j 列像素值设置为 128
使用at()进行遍历效率不高
迭代器-矩阵元素遍历
使用迭代器就不需要再使用两个for 和ij了。能够加大效率
Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{
// accept only char type matrices
CV_Assert(I.depth() != sizeof(uchar));
const int channels = I.channels();
switch(channels)
{
case 1:
{
MatIterator_<uchar> it, end;
for( it = I.begin<uchar>(), end = I.end<uchar>(); it != end; ++it)
*it = table[*it];
break;
}
case 3:
{
MatIterator_<Vec3b> it, end;
for( it = I.begin<Vec3b>(), end = I.end<Vec3b>(); it != end; ++it)
{
(*it)[0] = table[(*it)[0]];
(*it)[1] = table[(*it)[1]];
(*it)[2] = table[(*it)[2]];
}
}
}
return I;
}
选取图像局部
-
单行和单列选择
//参数 i 和 j 分别是行标和列标。例如取出 A 矩阵的第 i 行可以使用如下代码: Mat line = A.row(i); //例如取出 A 矩阵的第 i 行,将这一行的所有元素都乘以 2,然后赋值给第 j行,可以这样写: A.row(j) = A.row(i)*2;
-
选择多行或多列-Range
a. 该类有两个关键变量 star 和 end。Range 对象可以用来表示矩阵的多个连续的行或者多个连续的列。其表示的范围为从 start到 end,包含 start,但不包含 end。
b. Range 类还提供了一个静态方法 all(),这个方法的作用如同 Matlab 中的“:”,表示所有的行或者所有的列。//创建一个单位阵 Mat A = Mat::eye(10, 10, CV_32S); //提取第 1 到 3 列(不包括 3) Mat B = A(Range::all(), Range(1, 3)); //提取 B 的第 5 至 9 行(不包括 9) //其实等价于 C = A(Range(5, 9), Range(1, 3)) Mat C = B(Range(5, 9), Range::all());
-
感兴趣区域 (关于Rect类见openCV_Rect笔记)
a. 使用构造函数://创建宽度为 320,高度为 240 的 3 通道图像 Mat img(Size(320,240),CV_8UC3); //roi 是表示 img 中 Rect(10,10,100,100)区域的对象 Mat roi(img, Rect(10,10,100,100));
b. 使用括号运算符:
Mat roi2 = img(Rect(10,10,100,100));
c. 使用range对象:
//使用括号运算符 Mat roi3 = img(Range(10,100),Range(10,100)); //使用构造函数 Mat roi4(img, Range(10,100),Range(10,100));
-
对角线元素
a. 矩阵的对角线元素可以使用 Mat 类的 diag()函数获取,该函数的定义如下:
Mat Mat::diag(int d) const
b.参数 d=0 时,表示取主对角线;当参数 d>0 是,表示取主对角线下方的次对角线,如 d=1 时,表示取主对角线下方,且紧贴主多角线的元素;当参数 d<0 时,表示取主对角线上方的次对角线。
c.如同row()和col()函数,diag()函数也不进行内存复制操作,其复杂度也是O(1)。
Mat表达式-矩阵运算
利用 C++中的运算符重载,OpenCV 2 中引入了 Mat 运算表达式。这一新特点使得使用 C++进行编程时,就如同写 Matlab 脚本,代码变得简洁易懂,也便于维护。
如:C = A + B + 1;
以下为Mat支持的运算方法:
● 加法,减法,取负:A+B,A-B,A+s,A-s,s+A,s-A,-A
● 缩放取值范围:A * alpha
● 矩阵对应元素的乘法和除法: A.mul(B),A/B,alpha/A
● 矩阵乘法:A*B (注意此处是矩阵乘法,而不是矩阵对应元素相乘)
● 矩阵转置:A.t()
● 矩阵求逆和求伪逆:A.inv()
● 矩阵比较运算:A cmpop B,A cmpop alpha,alpha cmpop A。此处 cmpop可以是>,>=,==,!=,<=,<。如果条件成立,则结果矩阵(8U 类型矩阵)的对应元素被置为 255;否则置 0。
● 矩阵位逻辑运算:A logicop B,A logicop s,s logicop A,~A,此处 logicop可以是&,|和^。
● 矩阵对应元素的最大值和最小值:min(A, B),min(A, alpha),max(A, B),max(A, alpha)。
● 矩阵中元素的绝对值:abs(A)
● 叉积和点积:A.cross(B),A.dot(B)
Mat_类
如果使用 Mat_类,那么就可以在变量声明时确定元素的类型,访问元素时不再需要指定元素类型,即使得代码简洁,又减少了出错的可能性。
//在变量声明时指定矩阵元素类型
Mat_<uchar> M1 = (Mat_<uchar>&)M;
参考文献:
-
https://blog.csdn.net/zhjm07054115/article/details/25503781
-
OpenCV 入门教程.于仕琪/shiqi.yu@szu.edu.cn./http://www.opencv.org.cn
-
https://blog.csdn.net/kakiebu/article/details/79085556
-
https://blog.csdn.net/mc_linfen/article/details/82115594
编写时间
20210719
给个三连吧爹爹们,比心心
/*
* **************************************************************************
* ******************** ********************
* ******************** COPYRIGHT INFORMATION ********************
* ******************** ********************
* **************************************************************************
* *
* _oo8oo_ *
* o8888888o *
* 88" . "88 *
* (| -_- |) *
* 0\ = /0 *
* ___/'==='\___ *
* .' \\| |// '. *
* / \\||| : |||// \ *
* / _||||| -:- |||||_ \ *
* | | \\\ - /// | | *
* | \_| ''\---/'' |_/ | *
* \ .-\__ '-' __/-. / *
* ___'. .' /--.--\ '. .'___ *
* ."" '< '.___\_<|>_/___.' >' "". *
* | | : `- \`.:`\ _ /`:.`/ -` : | | *
* \ \ `-. \_ __\ /__ _/ .-` / / *
* =====`-.____`.___ \_____/ ___.`____.-`===== *
* `=---=` *
* **************************************************************************
* ******************** ********************
* ******************** ********************
* ******************** 佛祖保佑 永远无BUG ********************
* ******************** ********************
* **************************************************************************
*/