环境配置自己学 环境已经装好了

图像的存储形式

mat类

什么是mat类?

mat类是OPENCV里面用于储存数据的类型,与int,double等相同

储存的矩阵的形式

mat类的数据类型

矩阵头包含的是mat类所存储数据的具体参数

>行数和列数与尺寸对应

>数据类型是矩阵所储存的数据类型

>通道数是矩阵储存了几个通道的数据

>数据可以是图像,相机内参系数,神经网络的权重数等等

以3x4x2的矩阵为例,实际上就是一个行3列4通道2的矩阵

mat类的创建方式

用mat类

``` Cpp

cv::MAT:MAT(int rows,

		   int cols,

		   int type

		   )

//mat a (3,3,CV_8U);

```

type值的是矩阵中数据的数据类型,可以通过CV_8UC(n)来构建多通道矩阵,其中n最大可以取到512

利用size结构来构建

```Cpp

cv::Mat::MAT(Size size,

			int type

			)

```

和前面一样

用已有mat类构建新的mat类

```Cpp

cv::Mat::Mat(const MAT& m,

			const Range& rowRange,

			const Range& colRange)

mat(c,range(2,5))//不包含2和5行

```

如果不写则默认全部行/列

mat类的赋值

直接创建时候赋值

```Cpp

mat f(3,3,CV_8UC3,Scalar(0,0,255))

```

类方法赋值

a = Mat::eye(3,3,CV_8U)

枚举法

cv::Mat a = (cv::Mat<int>(3,3)<<1,2,3,4,5,6,7,8,9);

注意 <int>中间的内容不是CV而是C语言标准的int float型

循环法

```Cpp

cv::Mat c = cv::Mat_<int>(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;  
}  
}

```

事例

```Cpp

#include <opencv2/opencv.hpp>

#include<iostream>

using namespace cv;

using namespace std;

int main() {

	system("color F0");

	cv::Mat a = (cv::Mat_<int>(9,1) << 1, 2, 3, 4, 5, 6, 7, 8, 9);

	Mat b(Size(4, 4), CV_8UC1);

	Mat c0(5, 5, CV_8UC1, Scalar(4,5,6));

	Mat c1(5, 5, CV_8UC2, Scalar(4, 5,6));

	Mat c2(5, 5, CV_8UC3, Scalar(4, 5, 6));

	Mat d = Mat::diag(a);//diag里面必须是一维的矩阵

	Mat f = Mat(d, Range(1, 5), Range(1, 5));

	cout << c0 << endl;

	cout << c1 << endl;

	cout << c2 << endl;

	cout << a << endl;

	cout << d << endl;

	cout << f << endl;

}

```

输出

```

[  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;

 6;

 7;

 8;

 9]

[1, 0, 0, 0, 0, 0, 0, 0, 0;

 0, 2, 0, 0, 0, 0, 0, 0, 0;

 0, 0, 3, 0, 0, 0, 0, 0, 0;

 0, 0, 0, 4, 0, 0, 0, 0, 0;

 0, 0, 0, 0, 5, 0, 0, 0, 0;

 0, 0, 0, 0, 0, 6, 0, 0, 0;

 0, 0, 0, 0, 0, 0, 7, 0, 0;

 0, 0, 0, 0, 0, 0, 0, 8, 0;

 0, 0, 0, 0, 0, 0, 0, 0, 9]

[2, 0, 0, 0;

 0, 3, 0, 0;

 0, 0, 4, 0;

 0, 0, 0, 5]

```
mat类的读取

RGB模型

以临近的方式存储,存储完同一个像素的RGB之后再存储下一个

一个

3*3*3

的图像在内存里面实际上是一个三行九列的形式

a,cols得到列数

a.step以字节为单位的矩阵的有效宽度,step[0]是移动下一行的字节数

........

at方法读取

单通道

int value = (int)a.at<uchar>(0,0); uchar类型是0-255

多通道

```Cpp

cv::Vec3b vc3 = b.at<cv::Vec3b>(0,0);

int fist = (int)vc3.val[0]

//或者

int first = (int)vc3[0]

```

其中Vec3b表示一个元素的多个通道的数据,其中b代表uchar,s代表short,w代表ushort,d代表double,f代表float

矩阵元素地址定位方式访问元素

单通道

(int)(*(b.data+b.step[0]*row+b.step[1]*col+channel));

用x+y+z(x+y+z是指针的偏移量)来存储,可以直接获取(row,col)的数据

mat类的运算
mat类的四则运算

在进行运算时,要保证两个矩阵的尺寸和存储的数据类型也相同

a.dot(b)表示两个矩阵内积相乘,与维度无关,但长度和数值类型相同要求一样,既两个矩阵的个数应该相同,$2*3$ 可以和$6*1$的矩阵运算,两个矩阵的内积得到是一个数值

.mul()要求两个矩阵维度相同

[参考](https://blog.csdn.net/dcrmg/article/details/52404580)

opencv提供的运算函数

[4.6.0的相关函数](https://docs.opencv.org/4.6.0/) 直接在search里面搜索就行

两个矩阵最小值的得到的是一个矩阵,里面每一个元素都是对应元素的最小值