OPENCV第一章-绪论
环境配置自己学 环境已经装好了
图像的存储形式
mat类
什么是mat类?
mat类是OPENCV里面用于储存数据的类型,与int,double等相同
储存的矩阵的形式
矩阵头包含的是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之后再存储下一个
一个
的图像在内存里面实际上是一个三行九列的形式
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里面搜索就行
两个矩阵最小值的得到的是一个矩阵,里面每一个元素都是对应元素的最小值