专栏首页智能算法机器视觉算法(第9期)----OpenCV中最最最重要的类型

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

今天我们主要学习一下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<>()特化到矩阵所包含的数据类型,然后通过你想要数据的行和列的位置来访问该元素,简单实例如下:

cv::Mat m = cv::Mat::eye( 10, 10, 32FC1 );
printf(
    "Element (3,3) is %f\n",
    m.at<float>(3,3)
);

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

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()会返回这种类型的对象。因为迭代器具有足够的智能来处理连续的内存区域和非连续的内存区域,所以这种用法非常方便,不管在哪一种维度的数组中都非常有效。 所有的迭代器都必须在数组建立的时候声明并且指定一个对象类型。下面看一个简单的例子:

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!

本文分享自微信公众号 - 智能算法(AI_Algorithm),作者:左右Shawn

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-05-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 机器视觉算法(第8期)----OpenCV中事半功倍的工具函数

    上期我们一起学习了OpenCV中很重要的几个辅助对象, 机器视觉算法(第7期)----OpenCV中很重要的辅助对象 今天我们主要学习一下OpenCV中几个让人...

    智能算法
  • 机器视觉算法(第10期)----图像处理中64个常用的算子

    上期我们一起学习了OpenCV中最重要的数据类型数组Mat类, 机器视觉算法(第9期)----OpenCV中最最最重要的类型 从今天我们仍将以OpenCV为工具...

    智能算法
  • 通俗理解生成对抗网络(GANs)【下载PDF | 长文】

    GAN网络是近两年深度学习领域的新秀,火的不行,本文旨在浅显理解传统GAN,分享学习心得。现有GAN网络大多数代码实现使用Python、torch等语言,这里,...

    智能算法
  • AkShare-股票数据-复权后数据

    修改原有的基于新浪财经的A股历史行情数据接口,增加两个字段分别为:流动股本和换手率;同时增加直接输出前复权或者后复权的数据,方便用于回测。

    AkShare
  • flex中使用swc实现更好的界面代码分离

    前几天写过一篇"flash开发中如何实现界面代码分离",评论中 小-G 同学给出了更好的建议:swc ,今天试用了一下,果然比较embed swf来得更爽!同时...

    菩提树下的杨过
  • STREAM:一款scRNA-seq拟时分析工具

    scRNA-seq数据分析想必大家都比较熟悉了,自2014年nature biotechnology提出单细胞拟时分析或称为轨迹分析(Trajector...

    百味科研芝士
  • iOS - DeviceToken 解析

    在stackoverflow中有人说过这样的解析方式并不好,但是一直没有问题,所以大家也就习惯了这样的解析方式了,但是iOS13中这样的解析方式就有问题了 大...

    韦弦zhy
  • Item2教程

    Item2是简单来说就是一个终端,只不过外观很漂亮,大家都是颜控嘛哈哈哈~,它的实际功能在于提供了一些快捷键,提高了我们开发时候的日常效率。

    承苏凯
  • Golang中的热重启

    这几天在写组里的一个http框架,于是研究了下,在golang中如何实现服务的热重启,从而实现整个服务的重启可以实现对请求客户端的透明。

    netkiddy
  • 腾讯媒体开放战略:从社会化订阅市场入手

    罗超为钛媒体撰稿,2013年7月11日发表。 在日前召开的2013年合作伙伴大会上,腾讯宣布了其最新的开放战略,其中一个分支便是媒体开放平台战略,主要内容是资讯...

    罗超频道

扫码关注云+社区

领取腾讯云代金券