图像在OpenCV中都是通过Mat类来存储的,Mat可以用来表示N维矩阵,当然用的最多的还是二维矩阵。

      Mat类有两部分组成:第一部分是头信息,这些信息主要用来描述矩阵,比如矩阵维数ndims,rows,cols(这两个成员变量主要用于二维矩阵,用来表示行数和列数),size,sizes, type,step等等;第二部分是data信息,这是一个指针,指向Mat中存储的数据。

通过下面的代码,我们创建一个二维矩阵,并打印出矩阵:

//创建一个5*5的2维矩阵,数据类型为8bit的无符号数,数据为3个通道,初始值都为(0,0,255)

cv::Mat M(5,5, CV_8UC3, cv::Scalar(0,0,255));

cout << "M = " << endl << " " << M << endl << endl;

 

      这个矩阵的头信息和数据如下图所示:

      step表示每一行占据的字节数目,包括padding数据,其中每行中的padding数据有点吓到我了,我们只有15个uchar而已,没想到step竟然这么大,而且每次运行程序还是变化的,真正的数据大小是 M.cols*M.elemSize() = 15,我们可以通过函数M.isContinuous()知道当前矩阵是否有padding数据。

     没有padding数据时候,我们可以把矩阵的data当一维数据处理,数据长度就是rows*cols*elemSize()。

下面我看看如何访问矩阵中的元素,并进行操作:

1. 直接访问data,简单快速。

for(i=0; i< M.rows; i++)

{

    for(j=0; j<M.cols*M.elemSize(); j++)

   {

       printf ("%d ", M.data[i*M.cols*M.elemSize() + j]);

   }

   printf("\n");

}

或者用下面的代码:

uchar* p;

for( i = 0; i < M.rows; ++i)

{

    //得到第i行的指针,等价于 p = M.data + i*M.step

    p = M.ptr<uchar>(i);

    for ( j = 0; j < M.cols; ++j)

    {

      printf (" %d %d %d",p[j*3], p[j*3+1],p[j*3+2]);

     }

    printf("\n");

    或者我们也可以用at的方式得到数组元素,M.at<cv::Vec3b>(i,j)[2]得到元素中的第2个分量,如果M.at<uchar>(i,j),则只能取到元素的第一个分量。

//用at的方式访问矩阵元素
for(i=0; i< M.rows; i++)
    {
    for(j=0; j<M.cols; j++)
        {
        printf ("%d %d %d ", M.at<cv::Vec3b>(i,j)[0],M.at<cv::Vec3b>(i,j)[1], M.at<cv::Vec3b>(i,j)[2]);
        }
    printf("\n");
    }

}

2. 用c++迭代器的方式访问。

cv::MatIterator_<cv::Vec3b> it, end;

for( it = M.begin<cv::Vec3b>(), end = M.end<cv::Vec3b>(); it != end; ++it)

{

    printf("%d %d %d\n",(*it)[0], (*it)[1], (*it)[2]);

}

程序源码:工程FirstOpenCV2。

 

OpenCV学习(4) Mat的基本操作(1)的更多相关文章

  1. OpenCV学习(5) Mat的基本操作(2)

          本章我们学习一下Mat中的常用操作,因为在后面其它的教程中,我们经常要对图像进行各种处理,也要使用这些操作. 一. Mat的复制,就是从一个矩阵A,生成相关的另一个矩阵B. (1)使用赋值 ...

  2. OpenCV学习:Mat结构中的数据共享机制

    使用Mat类,内存管理变得简单,不再像使用IplImage那样需要自己申请和释放内存. Mat是一个类,由两个数据部分组成:矩阵头(包含矩阵尺寸,存储方法,存储地址等信息)和一个指向存储所有像素值的矩 ...

  3. OpenCV学习笔记——Mat类型数据存储

    CV_[The number of bits per item][Signed or Unsigned][Type Prefix]C[The channel number] 比如 CV_8UC3 表示 ...

  4. OpenCV学习(3)--Mat矩阵的操作

    CvMat的矩阵结构 typedef struct CvMat { //矩阵中元素的类型 int type; //行数据长度 int step; /* for internal use only */ ...

  5. opencv学习笔记(一)IplImage, CvMat, Mat 的关系

    opencv学习笔记(一)IplImage, CvMat, Mat 的关系 opencv中常见的与图像操作有关的数据容器有Mat,cvMat和IplImage,这三种类型都可以代表和显示图像,但是,M ...

  6. [OpenCV学习笔记2][Mat数据类型和操作]

    [Mat数据类型和基本操作] ®.运行环境:Linux(RedHat+OpenCV3.0) 1.Mat的作用: Mat类用于表示一个多维的单通道或者多通道的稠密数组.能够用来保存实数或复数的向量.矩阵 ...

  7. OpenCV学习C++接口 Mat像素遍历详解

    OpenCV学习C++接口 Mat像素遍历详解

  8. opencv学习笔记(六)直方图比较图片相似度

    opencv学习笔记(六)直方图比较图片相似度 opencv提供了API来比较图片的相似程度,使我们很简单的就能对2个图片进行比较,这就是直方图的比较,直方图英文是histogram, 原理就是就是将 ...

  9. opencv学习笔记(五)镜像对称

    opencv学习笔记(五)镜像对称 设图像的宽度为width,长度为height.(x,y)为变换后的坐标,(x0,y0)为原图像的坐标. 水平镜像变换: 代码实现: #include <ios ...

随机推荐

  1. 快速开发window服务器程序

    import service; service.startDispatchThread( 服务名 = function(serviceName,argv){ import service; var s ...

  2. day2 购物商城

    购物商城 商品展示.价格 买,加入购物车 付款,钱不够.(减商品,充值)

  3. ssh连接远程主机免密登入

    核心思想: 1.本地主机生成公钥私钥,私钥自己存着,公钥传到远程主机.ssh文件夹下authorized_keys文件(默认是这个,用追加的方式) 2.本地连接远程主机,公私钥对上就可以免密登入了. ...

  4. 什么是泛型 转载自http://www.blogjava.net/Jack2007/archive/2008/05/05/198566.html

    我们在编写程序时,经常遇到两个模块的功能非常相似,只是一个是处理int数据,另一个是处理string数据,或者其他自定义的数据类型,但我们没有办法,只能分别写多个方法处理每个数据类型,因为方法的参数类 ...

  5. 洛谷P2812 校园网络[数据加强版] [Tarjan]

    题目传送门 校园网络 题目背景 浙江省的几所OI强校的神犇发明了一种人工智能,可以AC任何题目,所以他们决定建立一个网络来共享这个软件.但是由于他们脑力劳动过多导致全身无力身体被♂掏♂空,他们来找你帮 ...

  6. RabbitMQ (十六) 消息队列的应用场景 (转)

    原贴 : http://blog.csdn.net/cws1214/article/details/52922267 消息队列中间件是分布式系统中重要的组件,主要解决应用耦合,异步消息,流量削锋等问题 ...

  7. 一个简单的ConnectionPool,手动搞

    看了一圈, 没看到稍微好用的ConnectionPool, 除了一个aiomysql, 但是这个是异步的, 我暂时没有用到这么高版本的Python, 所以就动手造一个轮子. 原理比较简单, 先造一个线 ...

  8. css去除chrome下select元素默认border-radius

    在mac下的chrome,对于select元素会默认有一个border-radius,当然有些情况下并不需要圆角,所以就要去掉. 比较常用的方法是: .select { -webkit-appeara ...

  9. Number 和 parseInt 区别

    把字符串 转换成 数字的时候, Number 有点不靠谱, 因为会对 '' 和 null 转换成0, parseInt 相对靠谱些; 判断是否是数值时, isNaN 对于字符串'2'的判断是数字, 对 ...

  10. FastReport.Net使用:[4]分组

    1.绘制报表标题和栏首. 2.设置报表栏,为数据区添加一个分组 3.右键分组页眉,在其右键菜单中选择“编辑”,显示分组编辑对话框. 设置分组条件,可直接通过下拉菜单选择Table表中的[学号]列:也能 ...