OpenCV入门之基本知识( 三 )


(1)利用默认构造函数
cv::Mat::Mat();
利用默认构造函数构造了一个Mat类,这种构造方式不需要输入任何的参数,在后续给变量赋值的时候会自动判断矩阵的类型与大小,实现灵活的存储,常用于存储读取的图像数据和某个函数运算输出结果 。
(2)利用矩阵宽、高和类型参数创建Mat类
通道数设置:(n),其中的n表示为n通道矩阵,其中n最大可以取到512 。
cv::Mat a(3,3,CV_8UC1);
通过输入矩阵的行、列以及存储数据类型实现构造 。这种定义方式清晰、直观、易于阅读,常用在明确需要存储数据尺寸和数据类型的情况下,例如相机的内参矩阵、物体的旋转矩阵等 。
(3)利用矩阵Size()结构和数据类型参数创建Mat类型
利用输入矩阵尺寸和数据类型构造Mat类的方法存在一种变形,通过将行和列组成一个Size()结构进行赋值 。
//用Size()结构构造Mat示例cv::Mat a(Size(480, 640), CV_8UC1); //构造一个行为640,列为480的单通道矩阵cv::Mat b(Size(480, 640), CV_32FC3); //构造一个行为640,列为480的3通道矩
利用这种方式构造Mat类时要格外注意,在Size()结构里矩阵的行和列的顺序与上一种方法相反,使用Size()时,列在前、行在后 。如果不注意同样会构造成功Mat类,但是当我们需要查看某个元素时,我们并不知道行与列颠倒,就会出现数组越界的错误 。
(4)利用已有Mat类创建新的Mat类
可以从一个较大的Mat中截取一个较小的Mat,类似于抠图 。但是,通过这种方式构造的Mat类与已有Mat类享有共同的数据,即如果两个Mat类中有一个数据发生更改,另一个也会随之更改
cv::Mat d = (cv::Mat_(1,5)<<1,2,3,4,5); cv::Mat e = cv::Mat::diag(d); cv::Mat f = cv::Mat(e,cv::Range(2,4),cv::Range(2,4));
d为第一个数组,e为第二个数组,f为第三个数组,是从第二个数组中截取的第二行到第四行,第2列到第4列 。
2.Mat类的赋值
(1)创建时赋值
【OpenCV入门之基本知识】该种方式是在构造的同时进行赋值,将每个元素想要赋予的值放入结构中即可,这里需要注意的是,用此方法会将图像中的每个元素赋值相同的数值,例如(0, 0, 255)会将每个像素的三个通道值分别赋值0,0,255 。我们可以使用如下的形式构造一个已赋值的Mat类 。
cv::Mat a(2, 2, CV_8UC3, cv::Scalar(0,0,255));//创建一个3通道矩阵,每个像素都是0,0,255cv::Mat b(2, 2, CV_8UC2, cv::Scalar(0,255));//创建一个2通道矩阵,每个像素都是0,255cv::Mat c(2, 2, CV_8UC1, cv::Scalar(255)); //创建一个单通道矩阵,每个像素都是255
在程序语句之前加上断点进行调试,用Image Watch查看每一个Mat类变量里的数据,结果如图所示,证明我们已成功构造矩阵并赋值 。
结构中变量的个数一定要与定义中的通道数相对应,如果结构中变量个数大于通道数,则位置大于通道数之后的数值将不会被读取,例如执行a(2, 2, , (0,0,255))后,每个像素值都将是(0,0),而255不会被读取 。如果结构中变量数小于通道数,则会以0补充 。
(2)类方法的赋值
以上四个方法是属于Mat类的类成员方法,直接调用即可 。diag()需要输入一个矩阵,然后diag将这个拒绝变为对角阵 。
cv::Mat d = (cv::Mat_(1,5),在定义时同样需要在括号中声明数据的变量类型 。Mat类迭代器的起始是Mat.begin< >(),结束是Mat.end< >(),与其他迭代器用法相同,通过“++”运算实现指针位置向下迭代,数据的读取方式是先读取第一个元素的每一个通道,之后再读取第二个元素的每一个通道,直到最后一个元素的最后一个通道 。