百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

OpenCV的mat类 opencv mat dims

liebian365 2024-11-02 13:36 19 浏览 0 评论

  opencv最初是Intel在俄罗斯的团队实现的,而在后期Intel对opencv的支持力度慢慢变小。在08年,美国一家机器人公司Willow Garage开始大力支持opencv,在得到支持后opencv更新速度明显加快,加入了很多新特性。在opencv1.x时代,数据类型为IplImage,在使用这种数据类型时,考虑内存管理称为众多开发者的噩梦。在进入到opencv2.x时代,一种新的数据类型Mat被定义,将开发者极大的解脱出来。所以在接下来的教程中,都会使用Mat类,而在看到IplImage类数据时也不要感到奇怪。
Mat类有两种基本的数据结构组成,一种是矩阵头(包括矩阵尺寸、存储方法、存储路径等信息),另一个是指向包含像素值的矩阵的指针(矩阵维度取决于其存储方法)。矩阵头的尺寸是个常数,但是矩阵自身的尺寸根据图像不同而不同。Mat类的定义有很多行,下面列出来一些关键属性如下所示:

class CV_EXPORTS Mat
{
public:
//......很多函数定义,在此省略
...
/*flag参数包含许多关于矩阵的信息,如:
Mat的标识
数据是否连续
深度
通道数目
*/
int flags;
int dims; //矩阵的维数,取值应该大于或等于2
int rows,cols; //矩阵的行列数
uchar* data; //指向数据的指针
int* refcount; //指向引用计数的指针,如果数据由用户分配则为NULL
//......其他的一些函数
};


可以把Mat看作是一个通用的矩阵类,可以通过Mat中诸多的函数来创建和操作多维矩阵。有很多种方法可以创建一个Mat对象。

Mat类提供了一系列的构造函数,可以根据需求很方便的创建Mat对象,其部分构造方法如下:

Mat::Mat() //无参数构造方法
/*创建行数为rows,列数为cols,类型为type的图像*/
Mat::Mat(int rows, int cols, int type)
/*创建大小为size,类型为type的图像*/
Mat::Mat(Size size, int type)
/*创建行数为rows,列数为cols,类型为type的图像
并将所有元素初始化为s*/
Mat::Mat(int rows, int cols, int type, const Scalar& s)
ex:Mat(3,2,CV_8UC1, Scalar(0)) //三行两列所有元素为0的一个矩阵
/*创建大小为size,类型为type,初始元素为s*/
Mat::Mat(Size size, int type, const Scalar& s)
/*将m赋值给新创建的对象*/
Mat::Mat(const Mat& m) //此处不会发生数据赋值,而是两个对象共用数据
/*创建行数为rows,列数为cols,类型为type的图像
此构造函数不创建图像数据所需内存而是直接使用data所指内存
图像的步长由step指定*/
Mat::Mat(int rows, int cols, int type, void* data, size_t step = AUTO_STEP)
Mat::Mat(Size size, int type, void* data, size_t step = AUTO_STEP) //同上
/*创建新的图像为m数据的一部分,其具体的范围由rowRange和colRange指定
此构造函数也不进行图像数据的复制操作,与m共用数据*/
Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)
/*创建新的矩阵为m的一部分,具体的范围由roi指定
此构造函数同样不进行数据的复制操作与m共用数据*/
Mat::Mat(const Mat& m, const Rect& roi)

  在构造函数中很多都涉及到type,type可以是CV_8UC1, CV_8UC3, …,CV_64FC4等。这些type中的8U表示8位无符号整数(unsigned int), 16S表示16位有符号整数,64F表示64位浮点数即double类型,C表示channel表示图像通道,C后面的数字表示通道数。如C1表示单通道图像,C4表示4通道图像,以此类推。如果需要更多的通道数,需要使用宏CV_8UC(n)重定义,其中n是需要的通道数。如

Mat M(3, 2, CV_8UC(5)); //创建3行2列通道为5的图像

  下面通过一个实例进行理解:

#include "stdafx.h"
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat M1(3, 2, CV_8UC3, Scalar(0, 0, 255));
cout << "M1 = " << endl << " " << M1 << endl;
Mat M2(Size(3, 2), CV_8UC3, Scalar(1, 2, 3));
cout << "M2 = " << endl << " " << M2 << endl;
Mat M3(M2);
cout << "M3 = " << endl << " " << M3 << endl;
Mat M4(M2, Range(1, 2), Range(1, 2));
cout << "M4 = " << endl << " " << M4 << endl;
waitKey(0);
return 0;
}

 运行结果如下:

也可以使用create()函数创建对象。如果create()函数指定的参数与图像之前的参数相同,则不进行实质的内存申请操作,如果参数不同,则减少原始数据内存的索引并重新申请内存。使用方法如下所示:

#include "stdafx.h"
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
Mat M1;
M1.create(4, 4, CV_8UC(2));
cout << "M1 = " << endl << " " << M1 << endl << endl;
waitKey(0);
return 0;
}

运行结果如下:

**值得注意的是使用create()函数无法初始化Mat类。

opencv也可以使用Matlab的风格创建函数如:zeros(),ones()和eyes()。这些方法使得代码非常简洁,使用也非常方便。在使用这些函数时需要指定图像的大小和类型。

在已有Mat类的基础上创建一个Mat类,即新创建的类是已有Mat类的某一行或某一列,可以使用clone()或copyTo(),这样的构造方式不是以数据共享方式存在。可以利用setTo()函数更改矩阵的值进行验证,方法如下:

程序中M4.row(0)就是指的M4的第一行,其它类似。必须值得注意的是:在本篇介绍中工较少了clone()、copyTo()、和”=”三种实现矩阵赋值的方式。其中”=”是使用重载的方式将矩阵值赋值给新的矩阵,而这种方式下,被赋值的矩阵和赋值矩阵之间共享空间,改变任何一个矩阵的值会影响到另外一个矩阵。而clone()和copyTo()两种方法在赋值后,两个矩阵的存储空间是独立的,不存在共享空间的情况。
运行结果如下

opencv中还支持其他的格式化输入与输出


#include "stdafx.h"
#include <iostream>
#include <opencv2/core.hpp>
#include <opencv2/highgui.hpp>
using namespace std;
using namespace cv;
int main()
{
//使用函数randu()生成随机数,随机数范围为0-255
Mat R = Mat(3, 2, CV_8UC3);
randu(R, Scalar::all(0), Scalar::all(255));
//以默认格式输出
cout << "R (default) = " << endl << R << endl << endl;
//以Python格式输出
cout << "R (python) = " << endl << format(R, Formatter::FMT_PYTHON) << endl << endl;
//以CSV格式输出
cout << "R (csv) = " << endl << format(R, Formatter::FMT_CSV) << endl << endl;
//以Numpy格式输出
cout << "R (numpy) = " << endl << format(R, Formatter::FMT_NUMPY) << endl << endl;
//以C语言的格式输出
cout << "R (c) = " << endl << format(R, Formatter::FMT_C) << endl << endl;
//2D点
Point2f P(5, 1);
cout << "Point (2D) = " << P << endl << endl;
//3D点
Point3f P3f(2, 6, 7);
cout << "Point (3D) = " << P3f << endl << endl;
//vec模板类,数值响亮输出
vector<float> v;
v.push_back((float)CV_PI); v.push_back(2); v.push_back(3.01f);
cout << "Vector of floats via Mat = " << Mat(v) << endl << endl;
//矢量输出
vector <Point2f> vPoints(20);
vector<Point2f> vPoints(20);
for (size_t i = 0; i < vPoints.size(); ++i)
vPoints[i] = Point2f((float)(i * 5), (float)(i % 7));
cout << "A vector of 2D Points = " << vPoints << endl << endl;
waitKey(0);
return 0;
}

输出结果如下所示:

【领QT开发教程学习资料,进Qt开发交流君羊:546183882 莬废领取,先码住不迷路~】

相关推荐

记录一个ComboBox的设置问题,你可能没遇到过

ComboBox这个控件使用频率太高了,我从VC6编程开始就用它,一直用到C#到现在的Net6,要说我这么一个编程老手还能在它身上栽跟头,我都不敢相信。但是今天竟然被它无情的戏耍了。记录下这个问题,看...

组合框(Combo Box)应用之一_combo简单组合框

【分享成果,随喜正能量】对别人期待太高,本质上是对自身无能的逃避和推托,与其期待别人,不如依靠自己。你不害怕孤独,就不再寄期望于他人陪伴;你有底气解决问题,就不在寄期望于他人向你伸出援手。一个人期待值...

Qt之QComboBox定制(二)_qt on_combobox_activated

上一篇文章Qt之QComboBox定制讲到了qt实现自定义的下拉框,该篇文章主要实现了列表式的下拉框,这一节我还将继续讲解QComboBox的定制,而这一节我将会讲述更高级的用法,不仅仅是下拉列表框,...

从零开始系列,用C#做软件产品:私人日记(九)ComboBox入门

第八节的内容早已写好发布,结果一直在审核中,不知道触动了哪条神经。评论中看到有一些网友都在问为什么不用WPF来开发,在这里我统一说明下:1)WPF界面设计相对复杂。由于它是矢量的,需要额外有很多容器做...

QT-QSharedMemory_qt450-10是什么材料

1.QSharedMemory介绍...

进入Python的世界19-pyqt6不只是UI设计,其他模块功能如何运用

今天是大年初四,继续探讨pyqt6,给出使用的建议。PyQt6绝不仅仅局限于UI设计...

从零开始学Qt - 10:一文读懂Qt的元对象系统

Qt本身并不是一种编程语言,它实质上是一个跨平台的C++开发类库。它是用标准C++编写的,为开发GUI应用程序和非GUI应用程序提供了各种类。Qt对标准C++进行了扩展,引入一些新的概念和功能,例如信...

QT实现抖动文字和滚动文字,附源码

前言不知道大家有没有发现今天的文章有什么不一样,哈哈,我自己胡拼乱凑弄了一个logo,好不好看就先不说了,最起码萌萌哒...当然这不是今天的重点,在做logo的时候,我原本想让文字动起来的,奈何技术有...

Qt Concurrent的使用_qt是什么意思

1.简介QtConcurrent命名空间提供了高级api,使得无需使用诸如互斥、读写锁、等待条件或信号量等低级线程原语就可以编写多线程程序。使用QtConcurrent编写的程序会根据可用的...

Qt使用FFmpeg播放视频_qt使用ffmpeg播放视频功能

一、使用场景...

Qt中使用匿名函数lambda表达式_匿名函数lambda

一、为什么要使用匿名函数lamdba首先,lambda表达式可以使代码变得简单,C++中,一个lambda表达式表示一个可调用的代码单元。如代码:...

EtherCAT运动控制卡开发教程之Qt(中):小线段连续轨迹加工

今天,正运动小助手给大家分享一下EtherCAT运动控制卡开发教程之Qt,主要介绍一下如何通过Qt编程实现小线段轨迹连续加工,暂停与继续。...

送亲人,用1小时制作精美电子相框 | Qt 示例

今天给大家分享:...

Python之面向对象:综合应用,基于GUI实现会动的游戏英雄

引言本打算以上一篇文章作为面向对象模块的收尾,但是,犹豫了许久,还是决定再补充一篇,也就是今天这篇文章,打算基于Python的PyQt6/PySide6框架开发一个GUI程序,模拟实现一个在电脑桌面活...

Qt——常用数据类型_qt基本数据类型

1.基础类型因为Qt是一个C++框架,因此C++中所有的语法和数据类型在Qt中都是被支持的,但是Qt中也定义了一些属于自己的数据类型,下边给大家介绍一下这些基础的数类型。...

取消回复欢迎 发表评论: