1.cv::Mat类简介

cv::Mat用于大型矩阵类型,这可以说是Opencv库整个c++实现的核心类。OpenCV库中绝大多数函数都是cv::Mat类的成员函数,或者以cv::Mat作为参数,或者以cv::Mat作为返回值。

cv::Mat类用于表示任意维度的dense数组。大多数图像数据都是存储在dense数组中,当然与之对应的就是sparse数组。

Note:若你对opencv2.1之前的版本较熟悉,你可能记得IplImage{IplImage}IplImage,CvMat{CvMat}CvMat。但在之后的版本中,这些类都没了,都被cv::Mat{cv::Mat}cv::Mat取代。

2.cv::Mat类中数据存储规则

cv::Mat类数据可以被用来表示各种维度的数组。数据存储在数组中,可以看作是一个n维的“光栅扫描顺序(raster scan order)”。

raster scan order解释:
在一维数组中,元素是顺序排列的。
在二维数组中,元素是被组织成行,每一行依次排列
在三维数组中,每一个平面可以认为二维数组,且每一个平面(二维数组)按行排列,且平面是一个接着一个。

每个数组都有一个标志元素,用来指示数组的内容。

  • dim:指定数组维度
  • rows/cols:指定数组的行数和列数(当dim>2时,这两个参数无效)
  • 指针:指向数组数据存储位置的数据指针
  • refcount:引用计数器,类似于利用cv::Ptr<>的引用计数器。该类成员的存在使得cv::Mat类能像数据智能指针一样被数据包含。

数据中的内存布局由数组step[]描述。cv::Mat类中,当下标为(i0,i1,’’’,iNd-1,iNd)时,数组的存储地址为:

对于二维数组而言:

cv::Mat中的每个数据元素本身可以是单个数字,也可以是多个数字。在多个数字的情况下,这个库称为多通道数组。事实上,n维数组和(n-1)维多通道数组实际上是非常相似的对象,但是由于在许多情况下,将数组看作向量值数组是有用的,比如图像而言通道为3表示彩色图像,通道为1表示灰度图像,所以库中对这种结构有特殊的规定。

在使用opencv2.1之前的版本中的IplImage{IplImage}IplImage时,有一个表征通道的成员变量:IplImage&MediumSpace;:&MediumSpace;:nChannels{IplImage\::\::nChannels}IplImage::nChannels。但在之后的版本中用cv::Mat类后,没有这个成员变量了,要查看通道数则需要调用cv::channels()。

要设置这种通道的区别的主要原因是内存访问。根据定义,数组的元素可以是向量值的部分。例如,一个数组可以被称为32位浮点数的二维三通道数组;在这种情况下,数组的元素是三个大小为12字节的32位浮点数。
当然在实际情况下,数据元素在内存中布局时,数组的行不是绝对按照顺序连续存放的;可能在行与行之间会有小的间隔。

这种填充的目的是提高内存访问速度。

n维单通道阵列与(n-1)维多通道阵列的区别在于,这种填充总是发生在完整行的末尾(也就是说,同一个通道中的元素总是顺序连续的)。

3.创建数组
cv::Mat m;
// Create data area for 3 rows and 10 columns of 3-channel 32-bit floats
m.create( 3, 10, CV_32FC3 );
// Set the values in the 1st channel to 1.0, the 2nd to 0.0, and the 3rd to 1.0
m.setTo( cv::Scalar( 1.0f, 0.0f, 1.0f ) );

可以利用cv::Mat类实例化一个变量来创建数组。当然利用这种方式创建的数组没有大小,也没有数据类型。在用这种方式创建数组后,之后可使用诸如create()这样的成员函数来分配数组大小,数据类型等参数。数组类型这一个参数决定了它具有哪种元素。

  • 第一个位置参数:传入的是数组的行数,此例中表示数组3行
  • 第二个位置参数:传入的是数组的列数,此例中表示数组10列
  • 第三个位置参数:传入的是数组元素的类型,此例中32bit浮点数,3通道

第三个位置参数,即指定元素的基本类型,也指定通道数。所有可能的类型都在头文件中定义了,一共有6*3=18种可选方式(从如下组合中选取):CV_{8U,16S,16U,32S,32F,64F}{1,2,3}CV\_{\{8U,16S,16U,32S,32F,64F\}\{1,2,3\}}CV_{8U,16S,16U,32S,32F,64F}{1,2,3}
所以按照上述的例子CV_32FC3表示32bit的浮点数,3通道。

cv::Mat m( 3, 10, CV_32FC3, cv::Scalar( 1.0f, 0.0f, 1.0f ) );

如上述代码所示,前一段介绍的代码可以整合构造过程中,这是另一种构造函数(带参数的)。

理解数组中的数据没有严格地附加到数组对象上是至关重要的。Mat对象实际上是一个数据区域的标头,原则上是一个完全独立的东西。例如,可以将一个矩阵n赋值给另一个矩阵m(即m = n)。在这种情况下,m内部的数据指针将被改变为指向与n相同的数据,之前m的数据指针(如果有的话)所指向的数据将被释放。同时,它们现在共享的数据区域的引用计数器将增加。最后,将更新m的成员(例如行,列和标志),以准确描述m中数据现在指向的数据。 这一切使得这些行为变得很方便,其中数组可以彼此分配,并且在幕后自动执行此操作以提供正确的结果。

4.cv::Mat对象的构造函数

下表是cv::Mat类可用的构造函数的完整列表。当然大部分情况下,我们只会用到下表中的某几个。

操作 例子
默认构造函数 cv::Mat;
按类型的2维矩阵构造函数 cv::Mat( int rows, int cols, int type );
带初始化值的按类型的2维矩阵构造函数 cv::Mat(int rows, int cols, int type,const Scalar& s);
具有预先存在的数据的2维矩阵构造函数 cv::Mat(int rows, int cols, int type,void* data, size_t step=AUTO_STEP);
按类型的2维数组构造函数(大小以sz为单位) cv::Mat( cv::Size sz, int type );
带初始化值的按类型的2维矩阵构造函数(大小以sz为单位) cv::Mat(cv::Size sz,int type, const Scalar& s);
具有预先存在的数据的2维矩阵构造函数(大小以sz为单位) cv::Mat( cv::Size sz, int type,void* data, size_t step=AUTO_STEP)
按类型的多维矩阵构造函数 cv::Mat(int ndims, const int* sizes,int type);
带初始化值的按类型的多维矩阵构造函数 cv::Mat(int ndims, const int* sizes,int type, const Scalar& s);
具有预先存在的数据的多维矩阵构造函数 cv::Mat(int ndims, const int* sizes,int type, void* data,size_t step=AUTO_STEP);

上表列出了cv::Mat类对象的基本构造函数,下表将列出拷贝构成函数,即如何从一个已知数组创建数组。除了基本的复制构造函数之外,还有三种方法用于从现有数组的子区域构造数组,以及一种使用某种矩阵表达式的结果初始化新矩阵的构造函数。

操作 例子
拷贝构造函数 cv::Mat( const Mat& mat );
仅拷贝指定行列的构造函数 cv::Mat(const Mat& mat,const cv::Range&rows,const cv::Range&cols);
仅拷贝指定区域的构造函数 cv::Mat(const Mat& mat,const cv::Rect& roi);
广义感兴趣区域复制构造函数,它使用范围数组从n维数组中进行选择 cv::Mat(const Mat& mat,const cv::Range*ranges);
复制构造函数,用其他矩阵的代数表达式的结果初始化m cv::Mat( const cv::MatExpr&expr );

上述拷贝构造函数中,利用子区域(也称为“感兴趣区域”)构造函数有三种形式:一种采用一系列行和一系列列(这仅适用于二维矩阵),一种使用cv :: Rect指定矩形子区域(也仅适用于二维矩阵),最后一个采用范围数组。 在后一种情况下,指针参数范围指向的有效范围的数量必须等于数组mat的维数。 如果mat是ndim大于2的多维数组,则必须使用第三个选项。

5.与旧版本之间的兼容问题

如果您正在维护包含C样式数据结构的opencv2.1版本之前的代码,您可能希望从现有的CvMat或IplImage结构创建新的C ++样式的cv :: Mat结构。 在这种情况下,我们有两个选择:

  • 在现有的数据上构建一个标记头m(通过将copyData设置为false)
  • 重新分配内存,并将老数据复制到m中(通过将copyData设置为true)
cv::Mat(
const CvMat* old,
bool copyData=false
);
cv::Mat(
const IplImage*
old,
bool copyData=false
);
6.模板构造函数

模板构造函数之所以被称之为模板构造函数,不是因为它们从cv::Mat构造出了一个模板类,而是因为它们从本身就是模板的东西(cv::Vec<>或cv::Matx<>),来创建cv::Mat类实例。所以模板构造函数能够用任意cv::Vec<>,cv::Matx<>类的实例来创建cv::Mat数组。或者将任意类型的STL库中的vector<>实例来构建相同类型的cv::Mat数组。

操作 例子
从相同类型的cv :: Vec构造类型为T和大小为n的一维数组 cv::Mat(const cv::Vec<T,n>&vec,bool copyData=true);
从相同类型的cv :: Matx构造类型为T且大小为m×n的二维数组 cv::Mat(const cv::Matx<T,m,n>&vec,bool copyData=true);
从包含相同类型元素的STL向量构造类型为T的一维数组 cv::Mat(const std::vector&vec,bool copyData=true);
7.Mat类的静态成员函数

cv::Mat类提供一些能够创建常用类的静态成员函数。

//创建一个大小为rows×cols的cv :: Mat,其中所有的值为类型为type(CV_32F等)的零
cv::Mat::zeros( rows, cols, type );//创建一个大小为rows×cols的cv :: Mat,其中所有的值为类型为type(CV_32F等)的一
cv::Mat::ones( rows, cols, type);//单位矩阵
cv::Mat::eye( rows, cols, type);

【opencv14】cv::Mat---Desne数组类相关推荐

  1. cv::Mat 与 CvMat的区别

    cv::Mat和CvMat都可以表示图像数据,只是却不明白他们之间到底什么区别,用CV::MAT 每次都有56byte的内存泄露.后来查看了源码才知道原来cv::Mat是一个类(Class),而CvM ...

  2. 【OpenCV3】cv::Mat类成员函数详解

    cv::Mat为OpenCV2和OpenCV3中最重要的类,可以毫不夸张得说,掌握了cv::Mat的操作,就掌握了OpenCV大半,这里将详细的介绍下cv::Mat类的成员函数及其使用. 1.clon ...

  3. cv mat 灰度值和_OpenCV2:总结篇 cv::Mat 类

    一.简介 在OpenCV中,可以用C++语法的Mat类来表示一张图像 也可以用C语法的lpllmage或CvMat结构体来表示一张图像 1.单通道像素值 2.多通道像素值 OpenCV默认颜色顺序为B ...

  4. OpenCV【零】—————cv::Mat——Mat对象创建方法

    OpenCV (一)--Mat对象创建方法 目录 OpenCV (一)--Mat对象创建方法 1. cv::Mat优点及原理(本质类) 2. Mat类拷贝及对象的创建方法 3. Mat 对象元素的高效 ...

  5. opencv mat用数组初始化_10、OpenCV中图像和Mat类型(一)

    Mat类型可以被认为是OpenCV库的核心. OpenCV库中绝大多数的函数都是Mat类的成员,以Mat作为参数,或者Mat作为返回值. Mat类用于表示任意维数的密集数组.即使对于数组中的该条目为零 ...

  6. 【OpenCV3】cv::Mat的定义与初始化

    cv::Mat是OpenCV2和OpenCV3中基本的数据类型,在cv::Mat类中,关于cv::Mat的定义和初始化有多种不同的形式,这里,将对其进行详尽的总结和介绍. 一.无数据拷贝的cv::Ma ...

  7. OpenCv学习笔记(二)—cv Mat学习

    由于在写上一篇图像的数据结构时,发现自己只知道CvMat,竟然还有Mat数据结构,真是无知了,看了这么多程序,貌似没有看到这个结构.有可能那些程序都是些老版本的例子,这是在2.0以后加上的,所以我也得 ...

  8. OpenCv中的cv::Mat::create()函数,cvRound(),cvFloor(),cvCeil()函数的详解l

    文件说明: cv::create()函数的详解 函数原型: inline void Mat::create(int _rows, int _cols, int _type) inline void M ...

  9. cv::Mat初识和它的六种创建方法

    cv::Mat 初识   Opencv种的Mat类,使得Opencv的编程更加的简单,程序员不用过多的去关注内存管理,并且发现Opencv的编程有点像不需要太多编程技术的Matlab一样,甚至有些函数 ...

  10. opencv 报错:Error: Assertion failed (data) in cv::Mat::at, file ... mat.inl.hpp, line 897(访问了不存在矩阵的像素)

    文章目录 opencv4报错 原因 解决方法 opencv4报错 这是源代码: #include <opencv2/opencv.hpp> #include <iostream> ...

最新文章

  1. 由于授权协议中的一个错误,远程计算机中断了会话
  2. 为什么用 抽象类,接口
  3. IntelliJ IDEA版本和junit版本不适配
  4. 今日直播 | 全国高校人工智能人才与科技莫干山论坛直播来袭!
  5. boost::reverse_lock相关的测试程序
  6. java离线语音识别_你家的油烟机,可以语音控制了吗?
  7. Celo计划推出一种与欧元挂钩的新稳定币
  8. 罗翔 ---- 理想主义的花
  9. Struts2学习笔记(八) 拦截器(Interceptor)(上)
  10. 会场安排问题NYOJ14
  11. UML学习(一)类图和对象图
  12. c3p0连接池配置模板,SSM中使用c3p0连接池配置属性
  13. USACO 4.2 The Perfect Stall 完美的牛栏(最大匹配)
  14. 哥尼斯堡的“七桥问题”(欧拉回路)
  15. ylbtech-DBD-WeShop(微店)
  16. 你以为 CSS 只是个简单的布局?
  17. 《咸鱼分享》DNS轮询
  18. 德鲁克:优秀的管理者,都做到了这3点
  19. 自动换行 word-break:break-all和word-wrap:break-word
  20. 对图片进行等比例压缩

热门文章

  1. STM32F103C8T6有128K的Flash
  2. lookup无序查找_excel无序查询 使用LOOKUP函数实现无序查询
  3. android sim卡状态改变广播,android监听SIM状态
  4. A-priori算法
  5. Hulu | 美国人民看电视流行趋势大赏(2020)
  6. 阿里云游戏服务器攻击怎么防御?
  7. bindingResult
  8. SpringBoot 整合ActiveMQ
  9. 延时调用的时候要注意
  10. 报表设计器是什么?报表自动生成器有那些?