图像识别入门(opencv入门)Mat类的学习

初识基于C++的opencv图像识别。
由于opencv既不是一个编程语言,也不是一个专门的软件,只是一个C++的图像识别库而已。且我自信我的C++基础还算牢固,故我直接从一些简单的源代码入手,一步步的去接触opencv库里面独有的一些图像处理函数与变量。
第一步接触的就是图像处理里面最基础的图像储存变量Mat。
Mat是一个代表多维密集单通道(或多通道)的数据类型,可以用来存储实数、复数向量或者灰度、彩色图像或者向量场,点云等等。
在这里解释一下图片的基本性质和类型,图片由像素点组成,比如有个图片的格式为100*100的,则这张图片图片中就有10000个像素点。

在opencv中Mat类主要包含两个数据部分,一个是矩阵头(包含矩阵尺寸、储存方式、储存地址等信息)和一个指向储存矩阵的指针。矩阵头是常数但矩阵本身的尺寸会依据图像的不同而不同,其本身的尺寸比矩阵头的尺寸大许多个数量级。因此在复制矩阵(Mat)对象时一般都是复制矩阵地址,最终都是指向同一个矩阵。
如:
Mat A, C;
A = imread("tutu.jpg");
Mat B(A);//通过拷贝构造函数进行复制
C = A;   //通过赋值运算符进行复制
以上两种方式最终都会指向同一个矩阵,只是对应的信息头不同而已(复制的只是信息头中的部分数据和矩阵指针)。
这时候再次提及之前没能搞懂的ROI感兴趣区域,其实ROI区域其实就是一个创建了只引用部分数据的信息头,与前面的差别也仅是一个是不同的对像,引用数据一样,一个是不同的对象,引用数据不同而已。

如果想要重新创建一个与之一模一样的矩阵,需要使用copyTo()或者是clone()这两个函数,如:
Mat F = A.clone();
Mat G;
A.copyTo(G);


创建Mat类的对象都需要指定对应储存元素的数据类型,即Type
Type的格式为: CV_<bit_depth>(S|U|F)C<number_of_channels>
1——bit_depth 即比特数,代表性数量有8bits, 16bits, 32bits, 64bits。一张图片如果他的每一个像素点在内存空间所占空间大小为8bits,则它对应的数字就是CV_8
2——S|U|F  S--代表signed int ——有符号整形数字
            U--代表unsigned int——无符号整形数字
            F--代表float —————单精度浮点型数字

3——C<number_of_channels>--代表该图片的通道数,如果想要单通道、三通道、四通道之外的通道数需要用()将通道数包起来。

如:CV_8UC(2)  ——就是代表二通道的元素类型。

PS 在这里的通道数是指用几个数值去描述这个像素点,如果只需要一个数值去描述像素点,则该图片为灰度图片。如果像素点有RGB三种颜色去描述,则该图片为彩色的。如果一个图片的像素点为四通道的,则第四个Alph通道为增加透明度的通道。

Mat 类对象创建的七种方法
方法一:
使用Mat的构造函数,如:
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255));
对于二维多通道图像,首先要定义其行数与列数,然后指定其储存元素的数据类型以及其通道数。
后面的Scalar是个short类型的向量,用它来初始化矩阵和标识图像的颜色。
方法二:
通过数组的帮助创建多维数组
int sz[3] = {2,2,2};
Mat L(3, sz, CV_8UC3, Scalar::all(0));
这种通过数组创建多维矩阵的方法只适用于维数>=2时。
第一个参数:维数
第二个参数:各个维度的尺寸
第三个参数:储存元素的类型
第四个参数:各个元素初始化数值
方法三:
为已存在的IplImage指针创建信息头得到相应的Mat对象。
IplImage* img = cvLoadImage("tutu.jpg", 1);
Mat mtx(img);
//转换IplImage指针为Mat中的指针部分,并创建与之相应的信息头。
方法四:利用Creat()函数
Mat M;
M.create(4,4,CV_8UC(2));
方法五:
使用Matlab式的定义,具体函数有:eye()、ones()、zeros().
其中eyes()代表初始化矩阵为对角矩阵
    ones()代表初始化矩阵为单位矩阵
    zeros()代表初始化矩阵为0矩阵
例:
Mat E = Mat::eye(4,4,CV_64F);
Mat O = Mat::ones(2,2,CV_32F);
Mat Z = Mat::zeros(3,3,CV_8UC1);


方法六:

对小矩阵使用逗号分隔式初始化函数
代码:
Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);

方法七:

本方法即使用成员函数clone或copyTo为一个已经存在的矩阵创建一个新的信息头(clone()能逐行复制)。

注意:

矩阵中每个像素点通道处进行赋值可以通过函数进行操作(例如randu()函数),如何产生填充各个通道的随机数可以看后面关于随机数的博客。


Mat 的格式化输出:

Mat类对 << 进行了重载,故我们可以通过cout 直接对矩阵进行输出操作,但该操作只能应用于二维矩阵。

在输出时也可以对输出格式进行修改,这时需要format()函数进行辅助操作。

例:

逗号分隔风格:
cout << format(r, Formatter::FMT_CSV) << ";" << endl;



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值