(接上篇)视觉处理中如何读取一个Mat类的数据?

1、Mat类数据的读取(Mat类元素的读取):也就是说我们如何读取一个图像中的像素值信息。这部分也是困扰初学者的问题。

我们的一个彩色图像每个像素通常都是由三个通道组成的:蓝色通道、绿色通道、红色通道。也就是BGR模型(MFC中使用RGB,但是OpenCV很特立独行,它是BGR模型。)

Mat数据在内存中存放时都是以临近方式存放的,也就是说我存一个像素的蓝色通道,绿色通道和红色通道,完事儿我再存储第二个像素的蓝色、绿色、红色通道。

假如我有个 3X3X3的矩阵,那么它在Mat类中应该是一个3行9列的矩阵,所以我们在读取的时候一定要注意,它不是3*3*3的形式,而是一个3*9的形式。

 1-1、Mat类的常用属性方法

Mat类常用的属性:

属性                      作用                                           举例

cols                     矩阵的列数                                 a.cols

rows                   矩阵的行数                                 a.rows

step                   以字节为单位的矩阵的

                         有效的宽度 这个值可以

                         与每个元素的字节数进行

                          运算,得到矩阵的列数。

elemSize()       每个元素的字节数

total()               矩阵中元素的个数 它等于函数乘以列数,

                       是整数类型。

channels         矩阵的通道数                                 a.channels

1-2、如何读取单通道和多通道的Mat数据

Mat元素的读取:使用 .at 方法读取Mat矩阵元素:  a. at(int row,int col)

单通道读取举例:int value=(int)a.at<uchar>(0,0);//读取第1行第1列的数值

              单通道的就是挨着的每个内存单位中存储的就是一个像素元素。我们只需要

              告诉at方法我们需要的是第几行第几列的这个元素的值。

注意:此时我们需要知道Mat类中的数据类型,我们在取出的时候也是需要知道Mat类中的

           存储的数据类型。<>尖括号就是声明了我们要取的这个Mat类的数据类型的。

           前边的(int)是加了强制转换的。

           我们读出的值虽然也是0-255但是,它在存储的时候其实是字符类型(uchar)存储的。所以

           要强制转换。

多通道读取举例:cv::Vec3b vc3= a.at<cv::Vec3b>(0,0);//读取一个三通道像素

                             int first=(int)vc3.val[0];  //获取该像素中的GBR中的G(蓝色)的数值

                           多通道在内存中存储时,(比如三通道)紧邻的3个内存块表示的是一个像素元素

                                    □□□□□□

                                    □□□□□□

                                    □□□□□□

                       你看这个3通道的mat值,其(0,0)就表示的是整个红色区的这个像素。而(0,1)则表

                       示整个绿色区域的这个像素值。

在OpenCV中定义了一种数据类型: Vec3b 表示一个三通道的矩阵。其中这三个通道中的每一个数据都是以b为代表的数据类型。

b代表的就是uchar类型(来,跟我读:安杈儿)。

如果我要是double类型那么就是:Vec3d。

同理:对于多种通道类型的像素在OpenCV中都定义了对应的数据类型:

比如Vec2b就是2通道的uchar。

比如Vec4i就是4通道的int类型的

读取多通道时,我们先将每个像素都存入了vec向量,然后我们如果想获取第一个元素的第一个通道值,再继续如下操作:int first=(int)vc3.val[0];

注意:我们想读取Mat类中的矩阵元素时我们肯定要知道这个矩阵是几通道的,而且矩阵中存是什么数据类型。如果不匹配的话是没有办法读取的。

1-3、介绍一种不需要知道数据类型的元素读取的方式:

不管是单通道的还是多通道的我都统一转换成单通道的,

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

这种方式比较直观不用考虑数据类型。

比如我想读取: 第一行 第二列 第三个通道 也就是X Y Z的思维方式去获取。

此时我使用指针的方式直接访问内存

1-4、使用代码展示如何读取Mat中的元素

#include<iostream>

#include<opencv2/opencv.hpp>//使用这个大的头文件可以将所有的opencv的头文件全都包含进去

using namespace std;

using namespace cv;

int main()

{

    system("color F0");//将C++黑色的界面调节成白色,方便看官看明白

    Mat a= (cv::Mat_<int>(3, 3) << 1,2,3,4,5,6,7,8,9);//利用枚举法创建一个单通道的Mat

    cout << a.at<int>(0, 0) << endl;//读取单通道中的元素,需要知道通道数和数据类型,

                                                      这是毫无疑问的。

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个通道

cv::Vec2b vec2b = c1.at<cv::Vec2b>(0, 0);//获取两通道中的某个元素

cout << vec2b << endl;//打印出这个数组

cout << (int)vec2b.val[0] << endl; //如果不加(int)强制转换的话,打印出来是方块儿,

                                                         因为我们的Mat矩阵中8u其实是Uchar类型

//使用通用方法读取,这里我们读到的是X为0 Y为1 Z为3的这样一个数据。

cout<< (int)(* (c2.data + c2.step[0] *2 /*row*/ + c2.step[1] *2/* col*/ +3/*

channel通道数*/));

return 0;

}

/结尾处 感谢上次几位大爷打赏给我吃的老冰棍儿,一并谢过///

  • 13
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

神 匠

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值