1、Mat类的介绍
什么是Mat类,以及Mat类能存储什么数据?
OpenCV里用于存储矩阵数据的类型,与C++中的int double等数据类型一样,例如:
133 141 147 153 171
128 152 133 132 154
152 187 136 127 145
也就是说OpenCV存储时是以一个矩阵类型的数据将图像的每个像素存储的!
自己理解:其实Mat类就是一个保存图像像素值的一个数据类型,他有自己的数据的结构。你包括抠图等等其实也就是截取这个Mat内部对应的像素点的信息,然后构成一个新的Mat对象,也就是一个新的图像了。
Mat类由矩阵头和数据两部分组成:
矩阵头:中包含了尺寸(640*480)、行数、列数(与尺寸是对应的)、数据类型、(这个mat类里存的是int 还是 double类型的数据)、通道数(2x3x4的图像)、引用次数等信息等(例如Mat a Mat b 两个数据对象公用的是一个mat数据图像 img,那么当删除img时他们两个引用的就是空的。还可以避免我在删除 a的img时 由于b还在引用,却给删了。)
数据部分:就是数据了。
2、Mat能存储什么样的数据类型呢?
cv::Mat_<_Tp> //自定义的类型
cv::Mat_<_Double> //
cv::Mat_<_Float> //
cv::Mat_<_uchar> //
cv::Mat_<_unsigned char> //
3、Mat类如何创建:三种常见的创建方式
第一种:
cv::Mat::Mat(int rows,/*构造矩阵的行数*/
int cols,/*矩阵的列数*/
int type /*矩阵中存储的数据类型此处除了CV_8UCI CV_64FC4等从1到4通道外,还 提供了更多通道的参数,通过CV_8UC(n)中的n来构建多通道矩阵,其中 最大可以取到512)
第二种:使用size结构
cv::Mat::Mat(Size size,/*通过Size(cols,rows)进行赋值*/
type:与前面一致)
第三种:利用已有的Mat类创建新的Mat类。
cv::Mat::Mat(const Mat& m, /*已经构建完成的Mat类矩阵数据*/
const Range & rowRange,/*在已有的矩阵中需要截取的行数范围,是一个Range变量,例如
从第2行到第5行可以标识为Range(2,5)*/
const Range & colRange=Range::all() /*在已有的矩阵中需要截取的列数范围,是一个
Range变量,例如 从第2列到第5列可以标识为Range(2,5)
其中截取的Mat类的数据是不包括5的 其实以0为起始基数算 的话只截取了3列和第4列。*/)
4、Mat类如何赋值
第一种创建时赋值:可以在创建时直接在后边加上一个参数
cv::Mat::Mat(int rows,
int cols,
int type,
const Scalar& s /*这个参数是给矩阵中每个像素赋值的参数变量,
Mat f(3,3,CV_8U,Scalar(1))
例如比如你的Mat是一个三通道的就可以在这个参数中给3个数 Scalar (0,0,255),四通道的 就给4个数 Scalar(1,1,1,1) Scalar可以给任意几个数
如果你是三通道的,Scalar给出了4个数,那最后的那个就被舍弃不用)
还有一种可以使用Mat类中的类方法进行赋值:
eye:单位矩阵
diag:对角矩阵
ones:元素全为1的矩阵
zeros:元素全为0的矩阵
使用方法:a=Mat::eye(行,列,type类型);
第三种赋值方式就是枚举法赋值:
cv::Mat a=( cv::Mat_<int>(3,3) << 1,2,3,4,5,6,7,8,9 );
声明一个mat类,并表明里边的数据类型和它是几行几列的,然后后边把具体的数据存入这
个3乘3的Mat里面
cv::Mat b=( cv::Mat_<double>(2,3) << 1.0,2.1,3.2,4.0,5.1,6.2 );
这里注意尖括号中给出的是int 或者 double 这是数据类型。而不是给CV_8U。
因为给成int 或double 是跟你计算机中的数据对应的。
5、创建与赋值的代码实际讲解:
#include<iostream>
#include<opencv2/opencv.hpp>//使用这个大的头文件可以将所有的opencv的头文件全都包含进去
using namespace std;
using namespace cv;
int main()
{
system("color F0");//将C++黑色的界面调节成白色
//Mat ooo(,);//创建一个Mat值时,VS会给出提示,有9种创建方式。
Mat a(3,3,CV_8UC1);//Mat创建方式的第一种行、列、数据类型。定义了一个单通道的Mat
Mat b(Size(4,4),CV_8UC1);//Mat第二种创建方式,使用Size创建一个Mat变量。
Mat c0(5,5,CV_8UC1,Scalar(4,5,6));//创建一个1通道的Mat值,赋值时却是赋值3个通道
Mat c1(5,5,CV_8UC2,Scalar(4,5,6));//创建一个2通道的Mat值,赋值时却是赋值3个通道
Mat c2(5, 5, CV_8UC3, Scalar(4,5,6));//创建一个3通道的Mat值,赋值时却是赋值3个通道
Mat d = (cv::Mat_<int>(1, 5) << 1, 2, 3, 4, 5);//创建一个1乘5这样的一个Mat,存储的是
//int 类型。并进行枚举法赋值
Mat e = Mat::diag(d);//使用一个已知的Mat矩阵,创建一个角点矩阵.
//创建角点矩阵它需要你输入的原有矩阵必须是
//一个1乘以N的矩阵原型。然后它把已有矩阵变成一个对角矩阵
Mat f = Mat(e, Range(2, 4)/*抠第二行和第三行下的*/, Range(3, 5)/*抠上述行中的第3列和
第四列*/);//抠图形式,在已有的Mat类中抠出一个Mat类
cout << c0 << endl;
cout << c1 << endl;
cout << c2 << endl;
cout << d << endl;
cout << e << endl;
cout << f << endl;
return 0;
}
运行结果:
[ 4, 4, 4, 4, 4;
4, 4, 4, 4, 4;
4, 4, 4, 4, 4;
4, 4, 4, 4, 4;
4, 4, 4, 4, 4]
[ 4, 5, 4, 5, 4, 5, 4, 5, 4, 5;
4, 5, 4, 5, 4, 5, 4, 5, 4, 5;
4, 5, 4, 5, 4, 5, 4, 5, 4, 5;
4, 5, 4, 5, 4, 5, 4, 5, 4, 5;
4, 5, 4, 5, 4, 5, 4, 5, 4, 5]
[ 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6;
4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6;
4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6;
4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6;
4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6, 4, 5, 6]
[1, 2, 3, 4, 5]
[1, 0, 0, 0, 0;
0, 2, 0, 0, 0;
0, 0, 3, 0, 0;
0, 0, 0, 4, 0;
0, 0, 0, 0, 5]
[0, 0;
4, 0]