前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器视觉算法(第9期)----OpenCV中最最最重要的类型

机器视觉算法(第9期)----OpenCV中最最最重要的类型

作者头像
智能算法
发布2019-05-17 16:19:26
1.2K0
发布2019-05-17 16:19:26
举报
文章被收录于专栏:智能算法

今天我们主要学习一下OpenCV中最重要的数据类型--数组Mat,这个结构可以视为是OpenCV所有C++实现的核心,OpenCV中所有主要函数都或是Mat类的成员,或是将Mat类作为参数,或是返回一个Mat类型。很少有函数和这三者都没有关系的。

每一个Mat矩阵,都包含一个表示它数据类型的flag成员,一个表示其维度的成员dims,分别表示行和列数的成员rows和cols(dims>2无效),一个指向真正数据存储地址的指针data,一个表示该内存区域有多少个引用的refcount成员,类似前面学的Ptr<>引用计数器,数据实体data的结构被step描述。

1. 构造函数
1.1 非复制构造函数

下面我们来看一下如何创建一个数组,下表是Mat类的构造函数(非复制构造函数):

上表的构造函数虽然很详细,但常用的也就前几个。

1.2 复制构造函数

下表是Mat类的复制构造函数,展示了如何从一个数组创建另一个数组,可以从一个已经存在的数组的子区域创建一个数组,或者从一些矩阵表达中生成一些新的矩阵,如下表:

1.3 模板构造函数

模板构造函数并不会从Mat中创建一个模板出来,而是根据模板创建一个Mat实例,这些构造函数允许通过模板类Vec<>或Matx<>来创建一个对应维度和类型的Mat,或者使用一个STL vector<>来创建一个相同类型的数组。如下表:

1.4 静态构造方法

Mat类也提供了一些静态方法来创建一些常用的数组,如下表,这些方法包括zeros(),ones(),eye(),对应的将建立一个全为0的矩阵,一个全为1的矩阵及一个单位矩阵。

2. 访问数组元素

在图像处理的过程中,经常会对图像的像素进行操作,那么该怎么访问图像的像素呢?通常用到的有三种访问数据的方法:

2.1 at直接访问法

直接访问是通过模板函数at<>来实现的。这个函数有很多种变体,对不同维度的数组有不同的参数要求。这个函数的工作方式是先将at<>()特化到矩阵所包含的数据类型,然后通过你想要数据的行和列的位置来访问该元素,简单实例如下:

代码语言:javascript
复制
cv::Mat m = cv::Mat::eye( 10, 10, 32FC1 );
printf(
    "Element (3,3) is %f\n",
    m.at<float>(3,3)
);

多通道数组的操作与单通道数组相类似,如下:

代码语言:javascript
复制
cv::Mat m = cv::Mat::eye( 10, 10, 32FC2 );
printf(
    "Element (3,3) is (%f,%f)\n",
    m.at<cv::Vec2f>(3,3)[0],
    m.at<cv::Vec2f>(3,3)[1]
);
2.2 指针访问法

为了访问二维数组,可以使用C风格的指针来指定某一行(由于数据是按行连续组织的,所以不能指定某一列),这个工作由cv::Mat类的成员函数ptr<>()完成。由于at<>()和ptr<>()都是模板函数,所以需要一个类型名来实例化。函数接收一个整型参数来指示希望指针指向的行,返回一个和矩阵原始数据类型相同的数据指针,比如,如果数组类型是CV_32FC3,那么它将会返回一个float*指针。 因此,给定一个类型为float三通道的矩阵mtx,那么结构体mtx.ptr<Vec3f>(3)将会返回mtx的第三行指向的第一个元素第一个通道的指针,这通常是访问数组最快的方式。

2.3 迭代器方式

OpenCV提供一对迭代器模板,一个用于只读(const)数组的和一个用于非只读的(ono-const)数组的。上述两个迭代器分别被命名为,MatConstIterator<>和MatIterator<>。Mat的成员函数begin()和end()会返回这种类型的对象。因为迭代器具有足够的智能来处理连续的内存区域和非连续的内存区域,所以这种用法非常方便,不管在哪一种维度的数组中都非常有效。 所有的迭代器都必须在数组建立的时候声明并且指定一个对象类型。下面看一个简单的例子:

代码语言:javascript
复制
int sz[3] = { 4, 4, 4 };
cv::Mat m( 3, sz, CV_32FC3 ); // A three-dimensional array of size 4-by-4-by-4
cv::randu( m, -1.0f, 1.0f ); // fill with random numbers from -1.0 to 1.0
float max = 0.0f; // minimum possible value of L2 norm
cv::MatConstIterator<cv::Vec3f> it = m.begin();
while( it != m.end() ) {
    len2 = (*it)[0]*(*it)[0]+(*it)[1]*(*it)[1]+(*it)[2]*(*it)[2];
    if( len2 > max ) max = len2;
    it++;
}
2.4 块访问方式

我们还可以将一个数组的子集作为另一个数组访问。这个子集可能是一行或者一列,也可能是原始数据的一个子集。如下表,有很多方法都可以让我们完成这个目的,所有的方法都是Mat的成员函数,并且都返回我们所请求的数组的子集。最简单的方法就是row()和col(),它将一个整型变量作为参数并返回这个变量所指引的行或列。

3. 矩阵操作

作为简单代数表达的补充,下表列出了可使用的代数操作的样例。

4. 其他成员函数

上面我们学习了大量的Mat的成员函数,但是还有一些很常用的成员函数,如下表:

至此,我们一起学习了OpenCV中最重要的一个类型,下一期,我们将一起学习图像处理中的矩阵操作。


智能算法,与您携手,沉淀自己,引领AI!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-13,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 智能算法 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 构造函数
    • 1.1 非复制构造函数
      • 1.2 复制构造函数
        • 1.3 模板构造函数
          • 1.4 静态构造方法
          • 2. 访问数组元素
            • 2.1 at直接访问法
              • 2.2 指针访问法
                • 2.3 迭代器方式
                  • 2.4 块访问方式
                  • 3. 矩阵操作
                  • 4. 其他成员函数
                  相关产品与服务
                  数据保险箱
                  数据保险箱(Cloud Data Coffer Service,CDCS)为您提供更高安全系数的企业核心数据存储服务。您可以通过自定义过期天数的方法删除数据,避免误删带来的损害,还可以将数据跨地域存储,防止一些不可抗因素导致的数据丢失。数据保险箱支持通过控制台、API 等多样化方式快速简单接入,实现海量数据的存储管理。您可以使用数据保险箱对文件数据进行上传、下载,最终实现数据的安全存储和提取。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档