当前位置: 首页 > 编程日记 > 正文

OpenCV 之 Mat 类

数字图像可看作一个数值矩阵, 其中的每个元素代表一个像素点,如下图所示:

   

   OpenCV 中,用 Mat 来表示该数值矩阵,它是很关键的一种数据结构,因为 OpenCV 中的大部分函数都和 Mat 有关:

   有的是 Mat 的成员函数;有的把 Mat 作为参数;还有的将 Mat 作为返回值

1  Mat 简介

Mat,在 OpenCV 中表示的是 N 维稠密矩阵,与稠密矩阵相对的是稀疏矩阵(只存储非零的像素值),后者常用于直方图处理中,OpenCV 中对应为 cv::SparseMat

如下所示:第一个为稠密矩阵的存储方式,存储所有的像素数值;第二个为稀疏矩阵的存储方式,只存储非零的像素值

$\quad \begin{bmatrix} 0 & 2 & 0 \\ 1 & 0 & 1 \\ 0 & 2 & 0 \end{bmatrix} $        $\quad \begin{bmatrix}  & 2 &  \\ 1 &  & 1 \\  & 2 &  \end{bmatrix} $

当 N=1 时,所有像素存储为一行;当 N=2 时,所有像素按照一行行的顺序排列;当 N=3 时,所有像素按照一面面的顺序排列,其中一行行的像素构成一个平面。

下图左,为灰度图的存储方式;图右,为 RGB 图像的存储方式,注意其存储顺序为 BGR (Blue->Green->Red)

    

2  Mat 特点

2.1  组成

Mat 类包含两部分,一是 矩阵头 (matrix header),二是 矩阵指针 (pointer to matrix),部分矩阵头如下:

int  flags;  // signaling the contents of the matrix
int  dims;   // dimensions
int  rows, cols;  // rows and columns 
MatSize  size;  // 
MatStep  step;  //

矩阵指针如下,指向包含所有像素值的矩阵

uchar* data;  // pointer to the data

2.2  赋值算子

Mat 类中的赋值算子 "=" 和 拷贝构造函数,涉及的是浅拷贝,因此,当执行这两个操作时,仅仅是复制了矩阵头。

如果想要深拷贝,达到复制图像矩阵的目的,应使用 clone()copyTo() 函数,如下图所示 (摘自参考资料 -- 4):

  

2.3  代码示例

下面是简单的验证,将矩阵 m3 通过 copyTo() 函数复制给 m1,而 m2 是通过 m1 直接赋值的,二者指向的是同样的数据。因此,如果改变了 m1,则 m2 对应的矩阵数值,也会进行相应的改变。

Mat m1(3, 3, CV_32FC1, Scalar(1.1f) );
cout << "m1 = " << endl << " " << m1 << endl << endl;
// using assign operator Mat m2
= m1; cout << "m2 = " << endl << " " << m2 << endl << endl;Mat m3(3, 3, CV_32FC1, Scalar(3.3f) ); m3.copyTo(m1); cout << "m1 = " << endl << " " << m1 << endl << endl; cout << "m2 = " << endl << " " << m2 << endl << endl;

3  Mat 创建

3.1  数据类型

在创建 Mat 之前,首先了解 Mat 中元素的数据类型,其格式为 CV_{8U, 16S, 16U, 32S, 32F, 64F}C{1, 2, 3}CV_{8U, 16S, 16U, 32S, 32F, 64F}C(n)

第一个 {} 内数据表示的意义如下:

CV_8U  - 8-bit 无符号整数 ( 0..255 )
CV_8S  - 8-bit 有符号整数 ( -128..127 )
CV_16U - 16-bit 无符号整数 ( 0..65535 )
CV_16S - 16-bit 有符号整数 ( -32768..32767 )
CV_32S - 32-bit 有符号整数 ( -2147483648..2147483647 )
CV_32F - 32-bit 浮点数 ( -FLT_MAX..FLT_MAX, INF, NAN )
CV_64F - 64-bit 浮点数 ( -DBL_MAX..DBL_MAX, INF, NAN )

第二个 {} 内的数据 或 (n),表示的是图像矩阵的通道数,CV_8UC3 则等价于 CV_8UC(3),表示的数据类型为:3通道8位无符号整数

3.2  创建方式

3.2.1  构造函数

创建一个 3 行 5 列,3 通道 32 位,浮点型的矩阵,通道 1, 2, 3 的值分别为 1.1f,2.2f,3.3f

Mat m(3, 5, CV_32FC3, Scalar(1.1f, 2.2f, 3.3f) );
cout << "m = " << endl << " " << m << endl << endl;

输出的矩阵如下:

3.2.2  create 函数

使用 Mat() + create() + setTo(),也可以构建如上的数值矩阵

Mat m;
// Create data area for 3 rows and 10 columns of 3-channel 32-bit floats m.create(
3,5,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(Scalar(
1.1f, 2.2f,3.3f)); cout << "m = " << endl << " " << m << endl << endl;

3.2.3  特殊矩阵

单位矩阵 (ones),对角矩阵 (eye),零矩阵 (zeros),如下所示:

// 单位矩阵
Mat O = Mat::ones(3, 3, CV_32F);
cout << "O = " << endl << " " << O << endl << endl;
// 零矩阵
Mat Z = Mat::zeros(3, 3, CV_8UC1);
cout << "Z = " << endl << " " << Z << endl << endl;
// 对角矩阵
Mat E = Mat::eye(3, 3, CV_64F);
cout << "E = " << endl << " " << E << endl << endl;

4  Mat 遍历

4.1  at<>() 函数

常用来遍历 Mat 元素的基本函数为 at<>(),其中 <> 内的数据类型,取决于 Mat 中元素的数据类型,二者的对应关系如下:

CV_8U  --  Mat.at<uchar>(y,x)
CV_8S  --  Mat.at<schar>(y,x)
CV_16U --  Mat.at<ushort>(y,x)
CV_16S --  Mat.at<short>(y,x)
CV_32S --  Mat.at<int>(y,x)
CV_32F --  Mat.at<float>(y,x)
CV_64F --  Mat.at<double>(y,x)

简单的遍历如下,使用了 Qt 的 qDebug() 来显示输出

Mat m1 = Mat::eye(10, 10, CV_32FC1);
// use qDebug() qDebug()
<< "Element (3,3) is : " << m1.at<float>(3,3); Mat m2 = Mat::eye(10, 10, CV_32FC2);
// use qDebug()
qDebug()
<< "Element (3,3) is " << m2.at<cv::Vec2f>(3,3)[0] << "," << m2.at<cv::Vec2f>(3,3)[1];

注意:at<>() 函数中 () 内行索引号在前,列索引号在后,也即 (y, x)

4.2  遍历方式

4.2.1  高效遍历

Mat& ScanImageAndReduceC(Mat& I, const uchar* const table)
{// accept only char type matricesCV_Assert(I.depth() == CV_8U);int channels = I.channels();int nRows = I.rows;int nCols = I.cols * channels;if (I.isContinuous()){nCols *= nRows;nRows = 1;}int i,j;uchar* p;for(i=0; i<nRows; ++i){p = I.ptr<uchar>(i);for (j = 0; j<nCols; ++j){p[j] = table[p[j]];}}return I;
}

4.2.2  迭代器遍历

Mat& ScanImageAndReduceIterator(Mat& I, const uchar* const table)
{// accept only char type matricesCV_Assert(I.depth() == CV_8U);const int channels = I.channels();switch(channels){case 1:{MatIterator_<uchar> it, end;for(it=I.begin<uchar>(), end=I.end<uchar>(); it!=end; ++it)*it = table[*it];break;}case 3:{MatIterator_<Vec3b> it, end;for(it=I.begin<Vec3b>(), end=I.end<Vec3b>(); it!=end; ++it){(*it)[0] = table[(*it)[0]];(*it)[1] = table[(*it)[1]];(*it)[2] = table[(*it)[2]];}}}return I;
}

4.2.3  耗时计算

比较上面两种方法的耗时,可使用如下代码来进行计算:

double t = (double)getTickCount();
// do something ...
t = ((double)getTickCount() - t)/getTickFrequency();
qDebug() << "Times passed in seconds: " << t << endl; // using qDebug()

参考资料:

1.  <Learning OpenCV3> chapter 4

2.  OpenCV Tutorials / The Core Functionality (core module) / Mat - The Basic Image Container

3.  OpenCV Tutorials / The Core Functionality (core module) / How to scan images, lookup tables and time measurement with OpenCV

4.  OpenCV基础篇之Mat数据结构

转载于:https://www.cnblogs.com/xinxue/p/7298683.html

相关文章:

hbase shell编码显示中文

最近测试hbase shell&#xff0c;碰到个中文显示编码问题&#xff0c;最后通过Python解决了问题&#xff0c;具体操作如下&#xff1a; hbase(main):015:0* scan ‘fr_test_hbase:test_log1’ ROW COLUMNCELL 10001 columninfo:name, timestamp1500448006065, valuetmr\xE4\xB…

AJAX范例大搜罗(转载)

1&#xff0e;每天一个AJAX 该网站提供了很多非常酷的AJAX例子&#xff0c;号称是每天更新一个。 网址&#xff1a;http://www.ajaxcompilation.com/ 2&#xff0e;210个AJAX框架 一个不错的提供Ajax范例的网站&#xff0c;Ajax框架已更新至210个。 网址&#xff1a;http:…

Hbase的过滤器查询

hbase过滤器的比较运算符&#xff1a; LESS < LESS_OR_EQUAL < EQUAL NOT_EQUAL <> GREATER_OR_EQUAL > GREATER > NO_OP 排除所有 hbase过滤器的比较运算符&#xff1a; BinaryComparator 按字节索引顺序比较指定字节数组&#xff0c;采用Bytes.compareTo(…

python的进程

多进程概念&#xff1a;   由于GIL的存在&#xff0c;python中的多线程其实并不是真正的多线程&#xff0c;如果想要充分地使用多核CPU的资源&#xff0c;在python中大部分情况需要使用多进程。python提供了非常好用的多线程包(multiprocessing)&#xff0c;只需要定义一个函…

071204 晴

晚上打算把周末的剩余任务做完去池袋kitty店预习作文把电脑慢的原因查出来电脑传照片的方法一部电影一本书一本杂志单词 转载于:https://www.cnblogs.com/loverain/archive/2007/12/04/982210.html

区块链深度好文

http://www.huhangfei.com/post/4/转载于:https://www.cnblogs.com/vinplezhang/p/7325161.html

工作流引擎设计之退回任务定义

退回&#xff08;Rollback Work Item&#xff09;退回是针对本人&#xff08;工作流参与者&#xff09;的“待办任务”的操作&#xff0c;即参与者主动退回待办任务列表中的任务。为什么要退回&#xff1f;参与者接受任务后&#xff0c;发现不应由自己办理此任务或上一步的执行…

HBase常用API操作

文章目录第一步&#xff1a;创建maven工程&#xff0c;导入jar包第二步&#xff1a;开发javaAPI操作HBase表数据1、创建表myuser2、向表中添加数据3、查询数据3.1、 按照rowkey进行查询获取所有列的所有值3.2、 按照rowkey查询指定列族下面的指定列的值3.3、 通过startRowKey和…

Kanade's trio 2017多校#3 trie

求数组中i<j<k 并且ai^aj<aj^ak的三元组组数 枚举插入ak&#xff0c;让ak中每一位作为最高位&#xff0c;查找字典树内最高位不同的数字数量 注意把ak的每个前缀做一个bad标记 存储让这个前缀作为i可以与字典树内形成i,j对的个数&#xff0c;这些不满足i<j ai : 1…

使用VS2005进行代码覆盖率分析

下面通过一个简单的例子来讲解VS2005是如何做代码分析的&#xff08;此处所做的代码分析是在单元测试之后进行的&#xff0c;其分析代码仍然使用上节的做和代码&#xff09; 1、上节的原始代码和单元测试代码分别如下&#xff1a; //原始代码 using System; using System.Colle…

云计算时代的数据库运行

云计算时代的高可用数据库是可扩展、容错且与任何私有云或公共云兼容的数据库实例。它们旨在提供业务连续性&#xff0c;而不会因任何类型的硬件或网络故障而导致用户体验的影响。其核心设计原则是消除任何单点故障&#xff0c;并提供平稳的故障转移体验。 公共云和私有云使企业…

Java:在Bean中使用PropertyChangeSupport支持PropertyChangeListeners

本文主要介绍如何使用PropertyChangeSupport类来支持关联属性事件的触发。author: ZJ 2007-8-3Blog: [url]http://zhangjunhd.blog.51cto.com/[/url]JavaBean的属性与一般Java程序中所指的属性&#xff0c;或者说与所有面向对象的程序设计语言中对象的属性是一个概念&#xff0…

【做题】SRM701 Div1 Hard - FibonacciStringSum——数学和式&矩阵快速幂

原文链接 https://www.cnblogs.com/cly-none/p/SRM701Div1C.html 题意&#xff1a;定义"Fibonacci string"为没有连续1的01串。现在&#xff0c;给出\(a,b\)&#xff0c;定义一个"Fibonacci string"的权值为\(x^a y^b\)&#xff0c;其中\(x\)为0的个数&…

scala定义抽象类与抽象字段

抽象类 和Java语言一样&#xff0c;scala中也可以定义抽象类 定义&#xff1a; 如果类的某个成员在当前类中的定义是不包含完整的&#xff0c;它就是一个抽象类 不完整定义有两种情况&#xff1a; 1.方法没有方法体&#xff08;抽象方法&#xff09; 2.变量没有初始化&#xf…

kuangbin专题16B(kmp模板)

题目链接: https://vjudge.net/contest/70325#problem/B 题意: 输出模式串在主串中出现的次数 思路: kmp模板 在 kmp 函数中匹配成功计数加一, 再令 j nxt[j] 即可. 感觉有点奇怪的就是我拿 A 题的模板写这题居然会 tle, 而拿这题的模板写 A 题又没有 A 题的模板跑的快...可能…

[转]C#日期格式化 文档

日期转化一 为了达到不同的显示效果有时&#xff0c;我们需要对时间进行转化&#xff0c;默认格式为&#xff1a;2007-01-03 14:33:34 &#xff0c;要转化为其他格式&#xff0c;要用到DateTime.ToString的方法(String, IFormatProvider)&#xff0c;如下所示&#xff1a; usin…

探讨ASP.NET AJAX客户端开发技术

一、 简介 在ASP.NET AJAX组件开发中&#xff0c;存在许多环节有待我们深入挖掘。如何让ASP.NET AJAX服务端控件更有效地利用客户端脚本来为控件添加强大的客户端功能&#xff1f;如何更为方便地访问控件访问的资源&#xff0c;等等。实践证明&#xff0c;要实现最终的应用程序…

mfc 应用程序 语言进行本地化

在软件国际化的今天,资源从代码中独立出来,使在不同语言操作系统下能运行不同语言版本的程序,是很有意义的事. MFC 7.0 及更高版本提供对附属 DLL 的增强支持&#xff0c;该功能有助于创建针对多种语言进行本地化的应用程序。附属 DLL 是一个纯资源 DLL&#xff0c;它包含应用程…

前端优化系列之一:dns预获取 dns-prefetch 提升页面载入速度

问题&#xff1a;怎么做到dns域解析&#xff1f;用于优化网站页面的图片问题&#xff1a;怎么提升网站性能&#xff1f;dns域解析&#xff0c;是提升网站的一个办法。DNS Prefetch&#xff0c;即DNS预获取&#xff0c;是前端优化的一部分。 一般来说&#xff0c;在前端优化中与…

暑假集训D15总结

考试 日常爆炸 T1数据背锅&#xff0c;回天乏力 推了两个小时的T2竟然莫名RE&#xff0c;我也是服了 T3考试时就没读懂题&#xff0c;做个鬼啊 今天一直在写某奇怪的技术贴&#xff0c;竟然没有写题解&#xff08;手动滑稽&#xff09; 希望明天不要乱炸吧 博客 强行推荐一波自…

maven-assembly-plugin和maven-shade-plugin打包区别及弊端

使用 maven 插件 maven-shade-plugin 对可执行 java 工程及其全部依赖 jar 进行打包 maven-shade-pluginmaven-assembly-pluginmavenjar打包 现在基本上都是采用 maven 来进行开发管理&#xff0c;我有一个需求是需要把通过 maven 管理的 java 工程打成可执行的 jar 包&#x…

【Spark】Spark基础练习题(一)

题目&#xff1a; 1、创建一个1-10数组的RDD&#xff0c;将所有元素*2形成新的RDD 2、创建一个10-20数组的RDD&#xff0c;使用mapPartitions将所有元素*2形成新的RDD 3、创建一个元素为 1-5 的RDD&#xff0c;运用 flatMap创建一个新的 RDD&#xff0c;新的 RDD 为原 RDD 每…

Python(27)_字符串的常用的方法2

#-*-coding:utf-8-*-字符串操作s " bowen " # 从右边删 s1 s.rstrip() print(len(s1)) s2 s1.lstrip() print(len(s2)) 从右边删除元素&#xff0c;从左边删除元素&#xff0c;这个在以后项目中经常用到 二、计算个数 #-*-coding:utf-8-*-字符串操作s " bo…

tensorflow1

1、什么是tensorflow tensorflow是一个开源软件库&#xff0c;使用data flow graphs进行数值计算&#xff0c;最初由Google大脑团队开发&#xff0c;用于机器学习和深度卷积网络的研究&#xff0c;同样适用于其他广泛的领域。 2、访问tensorflow官网&#xff1a;在Windows的hos…

大型企业门户网站设计开发一般性原则和建议

[适用范围] 本文所述的原则、建议适用于大型企业信息门户网站的设计和开发&#xff0c;注意不是小型企业网站、一般企业电子商务网站、企业级Web应用系统。 [一般性原则] 一、网站设计原则 第一原则&#xff1a;内容丰富、明确 网站主要是为浏览着提供信息服务的&#xff0c;作…

8月第3周回顾:四巨头发三大新闻 一报告引多家争议

8月15日是51CTO.com成立两周年的日子&#xff0c;网站举办了多种活动进行了庆祝&#xff1b;凑巧的是&#xff0c;IT界在本周也热闹非凡&#xff1a;微软、甲骨文、IBM和Sun联手送上三份重要新闻&#xff1b;国内一份个人安全的报告引起一场小小的风波——这些都足以让关注IT技…

车辆匹配和平均车速计算

数据测试内容以及详情见 https://github.com/xueyeyu/avgsp /* 作者&#xff1a;雪夜羽 平均车速计算&#xff08;sqlserver&#xff09;基于电警 QQ&#xff1a;1412900482 */ import java.sql.Connection; import java.sql.DriverManager; import java.sql.PreparedStatement…

为何 Map接口不继承Collection接口

1.首先Map提供的是键值对映射&#xff08;即Key和value的映射&#xff09;&#xff0c;而collection提供的是一组数据&#xff08;并不是键值对映射&#xff09;。 如果map继承了collection接口&#xff0c;那么所有实现了map接口的类到底是用map的键值对映射数据还是用collec…

Linux 开机网络无法自动连接配置、网络开机自动连接

第一步&#xff1a;查看开机后网络是否正常连接&#xff1f; 1、图形界面开机后直接看右上角的网络是否连接正常&#xff08;如图一&#xff09;。 图一&#xff08;表示未正常连接↑↑↑↑↑↑↑↑↑&#xff09; 2、如果是命令页面的&#xff0c;可以使用命令查看网络连接情况…

sql中将分隔字符串转为临时表的方法

问题: 要求将 一字符串 0,1,2,3,4,5 &#xff1b;将,分隔后的每一内容转为一行记录到数据库表中declare table_串转数组 table( adapt_object int default 0) declare tmp_str varchar(100) declare tmp_index int select tmp_index 1 select tmp_str 0,1,12,03,4,5,a,…