初始化

参考手册中的构造函数如下所示:

(1) Mat::Mat()

(2) Mat::Mat(int rows, int cols, int type)

(3) Mat::Mat(Size size, int type)

(4) Mat::Mat(int rows, int cols, int type, constScalar& s)

(5) Mat::Mat(Size size, int type, constScalar& s)

(6) Mat::Mat(const Mat& m)

(7) Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)  //data 为数组,使用 数组初始化 Mat ,注意 如果使用的是二维数组,记得使用 data[0]作为传入的参数,如果 data是一维,直接传入 data

(8) Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)

(9) Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)

(10) Mat::Mat(const Mat& m, const Rect& roi)

(11) Mat::Mat(const CvMat* m, bool copyData=false)

(12) Mat::Mat(const IplImage* img, bool copyData=false)

(13) template<typename T, int n> explicit Mat::Mat(const Vec<T, n>& vec, bool copyData=true)

(14) template<typename T, int m, int n> explicit Mat::Mat(const Matx<T, m, n>& vec, bool copyData=true)

(15) template<typename T> explicit Mat::Mat(const vector<T>& vec, bool copyData=false)

(16) Mat::Mat(const MatExpr& expr)

(17) Mat::Mat(int ndims, const int* sizes, int type)

(18) Mat::Mat(int ndims, const int* sizes, int type, constScalar& s)

(19) Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)

(20) Mat::Mat(const Mat& m, const Range* ranges)

OpenCV 里面的很多东西都会涉及到对Mat的操作,从基本的单个元素存取到整个Mat 数据的扫描。一般情况下用Mat.at(Point pt)就可以了,但是当有反复存取整个Mat数据的时候,整个扫描的效率就值得考虑了。有些同学对三通道或多通道的Mat数据的读取或许还有些疑问,同时,在debug和release的不同情况下,数据的读取速度也是不同的。所以这里再讨论一下几种数据存取的方法。

1 Mat.at

at 操作可以说是Opencv提供的官方操作, 具体执行如:

for (int i = 0; i<img.rows; i++){for (int j = 0; j < img.cols; j++){Vec3b& color = img.at<Vec3b>(i,j);//i是行,j是列,Point(x,y),x是列,y是行,注意color[0] = 0;color[1] = 255;color[2] = 255;}}

用at来扫描整个数据确实显得比较臃肿。估计是因为里面涉及到很多Opencv设定的指针之类的操作,我猜想是有很多需要动态链接的东西, 所以整个扫描过程比较慢,在debug模式下,会消耗很多时间。但是在release模式下,at操作将会快很多,仅仅比直接用指针的操作慢一点点,所以在真正运用的时候,at的速度并不慢。

2 指针 
Mat的数据结构是分为两部分的,一个是头,一个是数据。头就相当于很多文件前面的说明性内容,表明记录的是什么,怎么记录的,有什么特点,数据位置在哪之类。而数据就是单纯的数据,这个数据占用一串连续的存储空间。 数据和头在内存中的位置并不是必须连在一起的,但是头中肯定记录了数据的位置,这些数据的位置包括整个数据的起始和终点,每一行数据的起始位置等等。数据的存储顺序是按行进行的,从左到右,依次记录每个位置的所有通道的数据。所以说,只要我们知道了数据的起始位置和数据类型,那么利用指针就可以很方便快捷的扫描整个数据了。

利用指针读取数据的方法有三种,第一种是获取数据的开头后直接读取所有数据,数据的读取就像数组一样。这种方法要求头里面指定的整个数据必须连续。 像前面说的,一般情况下数据都是连续的,但是有时头里面指定的是某几个数据段,这时数据有可能就不连续。可以利用Mat.isContinuous()来查看头里面指定的数据是否是连续的。具体执行如:

if (img.isContinuous())//判断数据是否连续
{int data_length= img.rows*img.cols*img.channels();uchar* data= img.ptr<uchar>(0);//查找第一个数据的位置,这里指针的类型可以是各种数据结构,图像一般用CV_8U,所以这里利用unchar来作为指针类型。int channels = img.channels();for (int i = 0; i< data_length; i = i + channels){data[i] = 255;data[i+1] = 0;data[i+2] = 0;//这里我们认为图像是彩色的三通道,所以对每个像素的BGR通道分别进行单独操作}
}

第二种方法是获取每行数据的起始位置然后利用同样的原理进行数据的读取。因为一行内的数据肯定是连续的,所以不用检测数据是否连续。具体如下:

int channels = img.channels();
int j_end = img.cols*channel;for (int i = 0; i<img.rows; i++){uchar* data = img.ptr<uchar>(i);for (int j = 0; j<j_end; j = j + channels){data[j] = 255;data[j+1] = 0;data[j+2] = 255;}}//在实际应用中应注意数据的类型

在上面链接的那篇博客里,还介绍了一种指针的扫描方式,是利用Mat.step来返回每行数据的长度,然后据此来找到所有数据的位置。因为指针的位置是根据数据的开始位置和行数及列数来计算的,所以该方法也要求所有的数据都是连续的。具体如下:

int step = img.step;
int channels= img.channels();
uchar* data;
for (int i = 0; i<img.rows; i)
{for (int j = 0; j<img.cols; j++){data = img.data + i*step + j * channels;data[0] = 0;data[1] = 255;data[2] = 100;}
}//在实际应用中应注意数据的类型

利用指针来读取数据是最快的扫描方式,无论在debug还是release模式下。 一般情况下,循环中的操作越少速度会越快,所以第一种指针读取的速度是最快的,第二种涉及到读取每行的数据位置,速度稍慢一点,最后一种涉及到两个乘法,所以更慢一些。但是经过多次测试,这三种指针的读取速度都比Mat.at的速度要快一点。

总结:对Mat类型的数据的读取在一般情况下用at操作就可以了,但当涉及反复读取整个数据即需要多次扫描数据的时候,指针是比较高效的方法。好的编程风格确实可以极大提升程序的准确率和速度,节约程序员的时间。 在循环中尽量少涉及复杂的计算,特别是一些可以避免的重复计算。

Mat 读取数据 及效率对比相关推荐

  1. Python读取Excel表格效率对比(openpyxl、xrld、csv)

    文章目录 前言 安装模块 正文 一.openpyxl 读取 .xlsx 二.openpyxl 读取 .xlsx(只读模式) 三.xrld 读取 .xlsx 四.CSV 读取 .csv 结论 前言 搭了 ...

  2. MyBatis插入大量数据效率对比:foreach、SqlSession、sql三种方式批量插入

    用mybatis插入数据执行效率对比,对比三种方式(测试数据库为MySQL), 使用 SqlSessionFactory,每一批数据执行一次提交 使用mybatis-plus框架的insert方法,f ...

  3. java解析tfrecord_TensorFlow高效读取数据的方法——TFRecord的学习

    摘要: ortmatplotlib.pyplotaspltimportcv2defshow_image(title,image):'''显示图片:paramtitle:图像标题:paramimage: ...

  4. python如何读取tfrecord_tensorflow学习笔记——高效读取数据的方法(TFRecord)

    关于TensorFlow读取数据,官网给出了三种方法: 供给数据(Feeding):在TensorFlow程序运行的每一步,让python代码来供给数据. 从文件读取数据:在TensorFlow图的起 ...

  5. 【Python | opencv+PIL】常见操作(创建、添加帧、绘图、读取等)的效率对比及其优化

    一.背景 本人准备用python做图像和视频编辑的操作,却发现opencv和PIL的效率并不是很理想,并且同样的需求有多种不同的写法并有着不同的效率.见全网并无较完整的效率对比文档,遂决定自己丰衣足食 ...

  6. Java文件读取方式和效率性能对比

    场景描述 文件大小 8.67G的json文件,一共670万行. 服务器内存:2g.(只能读取一定缓冲数据,然后处理后继续读取,不能一次性加载到内存) 读取文件的内容出来,并未做业务处理. 读取方式和性 ...

  7. 线程的创建 验证线程之间共享数据 守护线程 线程进程效率对比 锁 死锁 递归锁...

    线程(from threading import Thread):CPU调度的最小单位 线程的两种创建方式:方式一: 1 from threading import Thread 2 def f1(i ...

  8. QT Creator使用matlab库文件读取.mat文件数据

    QT Creator使用matlab库文件读取.mat文件数据 一.环境配置 二.关于编程介绍 三.关于使用函数的介绍 1:关于假设数据类型介绍 2:关于使用函数介绍 一.环境配置 第一步先点开我的电 ...

  9. python使用h5py读取mat文件数据

    目录 一.matlab生成.mat文件 二.读取mat文件数据 一.matlab生成.mat文件 a=[]; List =dir('C:\Users\Administrator\Desktop\cod ...

最新文章

  1. cf792b循环链表
  2. PHP中ini_set和ini_get函数用法简介
  3. 整数数组查找java_使用Java编写程序以查找整数数组中的第一个非重复数字?
  4. openfoam安装中出现allmake error_深入理解 OpenFOAM 环境与编译过程
  5. Android之倍数提高工作效率的 Android Studio 奇技
  6. 网络操作系统课后练习第三章
  7. Zabbix 3.0 安装部署
  8. 【软件测试】白盒测试的条件覆盖标准强于判定覆盖(错)
  9. httos双向认证配置_Fabric区块链如何启用双向TLS?
  10. XML 数据挖掘 之 挖掘 XML 关联规则
  11. 【原创】ourphp一处SQL注射
  12. Pannellum:实例之全景图预览
  13. java pdf查看_Java检查PDF文件是否损坏
  14. 图片表格如何转换成excel表格
  15. postgresql中case when的使用
  16. SLA是什么意思 ?
  17. BZOJ 1189([HNOI2007]紧急疏散evacuate-网络流二分+拆点)
  18. Scikit-Learn机器学习(knn算法)
  19. 医院应如何有效实施迅速合理的安全疏散系统
  20. windows 10 ISO 纯净版 官方来源

热门文章

  1. 15-5 电子词典
  2. 渗透攻击exp共享站点(建议收藏❤️)
  3. 计算机网络——各种计算
  4. 华硕编程竞赛11月JAVA专场 G题飞行棋 题解
  5. 2021年安全员-A证复审考试及安全员-A证考试试题
  6. 《高质量读研:教你如何写论文、做科研》- 张军平
  7. Jenkins-springcloud项目打包并上传docker仓库
  8. qemu stm32环境搭建教程
  9. 高通骁龙855,麒麟980,A12,Exynos 9820芯片参数比较
  10. matlab yticklable,Matlab绘制XTickLabel有效字符串(Matlab Plot XTickLabel valid strings)