Opencv3基础学习

【opencv14】cv::Mat类创建数组

2018-12-21  本文已影响14人  yuanCruise

0.给自己打个小广告

本人211硕士一枚,目前从事深度学习,机器学习计算机视觉算法行业,目前正在将我的各类学习笔记发布在我的公众号中,希望感兴趣一起学习的同学们可以关注下~~~
本人微信公众号:yuanCruise


1.cv::Mat类简介

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

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

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

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

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

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

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

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


对于二维数组而言:



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

在使用opencv2.1之前的版本中的{IplImage}时,有一个表征通道的成员变量:{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()这样的成员函数来分配数组大小,数据类型等参数。数组类型这一个参数决定了它具有哪种元素。

第三个位置参数,即指定元素的基本类型,也指定通道数。所有可能的类型都在头文件中定义了,一共有6*3=18种可选方式(从如下组合中选取):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结构。 在这种情况下,我们有两个选择:

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<T>&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);

上一篇 下一篇

猜你喜欢

热点阅读