【OpenCV】浅谈 Mat 类

这篇具有很好参考价值的文章主要介绍了【OpenCV】浅谈 Mat 类。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1、Mat类介绍

Mat 类是一个用于保存图像数据或者矩阵数据的数据结构,可以说是一个矩阵类, 在OpenCV 1.0时代,存储图像数据都是使用C语言中的一个结构体IplImage,很麻烦的是IplImage需要在程序结束的时候手动释放内存,就跟我们现在malloc过来的堆区空间一样。 不过随着OpenCV版本的更新迭代,Mat类的出现非常便捷的解决了这个问题。

Mat类用来保存矩阵类型的数据信息,包括向量、矩阵、灰度或彩色图像等数据。Mat类分为矩阵头和指向存储数据的矩阵指针两部分。矩阵头中包含矩阵的尺寸、存储方法、地址和引用次数等。矩阵头的大小是一个常数,不会随着矩阵尺寸大小而改变。在绝大多数情况下矩阵头大小远小于矩阵中数据量的大小,因此图像复制和传递过程中主要的开销是存放矩阵数据。为了解决这个问题,在OpenCV中复制和传递图像时,只是复制了矩阵头和指向存储数据的指针,因此在创建Mat类时可以先创建矩阵头后赋值数据。

例如下面的一段程序:

cv::Mat m;   // 创建一个名为m的矩阵头
m = cv::imread("C:\test.jpg");  // 向a中赋值图像数据,矩阵指针指向像素数据
cv::Mat tmp = m;  // 复制矩阵头并命名为tmp

2、构造函数

2.1、默认构造函数

cv::Mat::Mat()

默认构造函数:生成一个矩阵并由OpenCV提供的函数(一般是Mat::create() 和 cv::imread()来分配内存空间)。
上面说到Mat类分为两个部分:矩阵头和指向像素数据的矩阵指针。

矩阵头:包括数字图像的矩阵尺寸、存储方法、存储地址和引用次数等,矩阵头的大小是一个常数,不会随着图像的大小而改变,但是保存图像像素数据的矩阵则会随着图像的大小而改变,通常数据量会很大,比矩阵头大几个数量级。这样,在图像复制和传递过程中,主要的开销是由存放图像像素的矩阵而引起的。因此,OpenCV使用了引用次数,当进行图像复制和传递时,不再复制整个Mat数据,而只是复制矩阵头和指向像素矩阵的指针,如上面的示例。

上面的m和tmp有各自的矩阵头,但是其矩阵指针指向同一个矩阵,也就是其中任何一个改变了矩阵数据都会影响另外一个。那么,多个Mat共用一个矩阵数据,最后谁来释放矩阵数据呢?

这就是引用计数的作用,当Mat对象每被复制一次时,就会将引用计数加1,而每销毁一个Mat对象(共用同一个矩阵数据)时引用计数会被减1,当引用计数为0时,矩阵数据会被清理。

2.2、常用构造函数—1
cv::Mat::Mat(int rows, int cols, int type);

重载的构造函数,这也是常用的构造函数之一,在创建对象的同时,提供矩阵的大小(rows,行数; cols,列数;)以及存储类型(type)。
该类型表示矩阵中每一个元素在计算机内存的存储类型,如CV_8UC3,具体含义为“3通道8位无符号数”。

Mat src(10,10,CV_32FC3);  // 表示src是一个10*10的矩阵,且矩阵元素以32位float类型存储

类似,OpenCV还提供了一种Size()数据结构来构造Mat对象

2.3、常用构造函数— 2
cv::Mat::Mat(Size size, int type);

Size类等效于一个成对数据,size::Size(cols,rows),特别注意cols和rows的位置,和2.2中的构造函数是相反的。

Mat Src1(3,4,CV_32FC3);
Mat src2(Size(3,4),CV_32FC3);
cout << "src1.rows= " << src1.rows << "src1.cols= " << src2.cols << endl;
cout << "src2.rows: " << src2.rows << "src2.cols: " << src2.cols << endl;
cout << "src1.size="<<src1.size() << endl <<"src2.size=" << src2.size() <<endl;

不得不说,这个Size类的数据结构有点“反人类”,但这样做的好处是方便了计算机内部的运算(比如OpenCV很多函数计算Size相关的数据也是按这个顺序来的,具体为什么这样,我也不太清楚,个人理解为行业标准);

还有,我们平时所说分辨率,也是Size的类型,比如屏幕分别率 1440*900,其中cols=1440,rows=900;

2.4、常用构造函数— 3
cv::Mat::Mat(int ndims, const int* sizes, int type, const Scalar& s);

该构造函数与使用了Scalar参数,作用是能够通过Scalar数据类来初始化元素值,例如,我们要生成一张白色背景的图片:

Mat whiteImage(500, 500, CV_8UC3, Scalar(255,255,255));
imshow("demo", whiteImage);  // 显示白色背景图片

其中,(255,255,255)对应以8位无符号数存储,RGB色域的白色值。

2.5、常用构造函数— 4
cv::Mat::Mat(const Mat& m);

引用m矩阵,注意,这里是引用值;

3、成员函数

3.1、at函数

at函数的功能是访问矩阵元素,根据不同的使用场景,有多个重载函数可供选择。

如,访问一个二维的矩阵,可用at函数原型为:

_Tp& cv::Mat::at(int i0,int i1)

示例:

Mat image = imread("test.jpg");
int elem = image.at<int>(0,0);   // 访问test.jpg图像的(0,0)元素
3.2、channels函数

channels函数的功能是返回图像的通道数,原型如下:

int cv::Mat::channels()  const

示例:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat image = imread("C:/openCV_image/hutao.jpeg");
    int nChannel = image.channels();

    cout << "hutao.jpeg的通道数: " << nChannel << endl;  // 3
    
    return 0;
}
3.3、clone函数

clone函数的功能是复制一个矩阵给新的矩阵.

//原型如下:
Mat cv::Mat::clone()    const

示例:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat image = imread("C:/openCV_image/WeChatTouXiang.jpg");
    int nChannel = image.channels();

    cout << "WeChatTouXiang.jpg的通道数: " << nChannel << endl;

    Mat cloneImage;
    cloneImage = image.clone();  //复制image矩阵赋值给cloneImage矩阵


    imshow("aaa", image);
    waitKey(0);
    
    return 0;
}
3.4、convertTo函数

convertTo函数的功能是转换矩阵存储类型。

// 函数原型:
void cv::Mat::convertTo(OutputArray m,int rtype,double alpha = 1,double beta = 0)   const

转换矩阵存储类型的具体计算公式如下:

m(x,y)=saturate_cast<rType>(α(∗this)(x,y)+β)

理解不了,暂时我也只是做个记录,用网上的说法解释一下:
m是输入矩阵,rtype是目标类型,alpha是放缩系数,beta是增减标量

3.5、copyTo函数

copyTo函数的功能:从m矩阵复制data数据单元,与clone函数的作用类似,原型如下:

void cv::Mat::copyTo(OutputArray    m)  const

示例就不写了,和clone一样的用法。

3.6、create函数

create函数的功能:分配矩阵的存储单元,一般和默认构造函数配合使用,原型如下:

void cv::Mat::create(int rows,int cols,int type) 
3.7、depth函数

depth函数的功能:返回图像深度,即矩阵元素的存储方式

原型如下:

int cv::Mat::depth()    const

示例:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    Mat image = imread("C:/openCV_image/WeChatTouXiang.jpg");
    int nDepth = image.depth();

    cout << "image图像深度:" << nDepth << endl;
    
    return 0;
}
3.8、pop_back函数

pop_back函数的功能:弹出最后一行元素,原型如下:

void pop_back(size_t nelems=1);

暂时还没用上此函数。

3.9、total函数

total函数的功能:返回矩阵的元素总个数,原型如下:

size_t total() const;

示例如下:

#include <opencv2/opencv.hpp>
#include <iostream>

using namespace std;
using namespace cv;

int main()
{
    //Mat image = imread("C:/openCV_image/WeChatTouXiang.jpg");
    //int nDepth = image.depth();

    Mat image(30, 40, CV_8UC3);  //创建一个30*40  8位3通道无符号类型的矩阵

    size_t n_total = image.total();

    cout << "image图像元素个数:" << n_total << endl;   //返回1200  30*40 = 1200个像素点
    
    return 0;
}
3.10、Mat::zeros()函数
Mat m = Mat::zeros(2, 2, CV_8UC3);

相当于创建一张黑色的图,每个像素的每个通道都为0,Scalar(0,0,0);

3.11、 Mat::ones()函数
Mat m = Mat::ones(2, 2, CV_8UC3); 相当于:Mat m = Mat(2, 2, CV_8UC3, 1);

OpenCV replaces 1 with Scalar(1,0,0)相当于每个像素的第一个通道为1,其余两个通道为0;

3.12、release函数

release函数的功能:在必要的情况下,递减引用计数并释放该矩阵。

void Mat::release()

该方法递减与矩阵的数据关联的引用计数。当引用计数减为0时,矩阵的数据将被释放,数据和引用计数器指针设置为 NULL。如果矩阵头指向外部数据集 (见 Mat::Mat()), 引用计数为 NULL,并且该方法在这种情况下无效。

可以手动调用此方法强制矩阵数据释放。但由于这种方法在析构函数中是自动调用的,或以更改数据指针的其他方法,因此通常不需要调用这个函数。在支持它的平台上,引用计数器递减并检查是否为0 是一个原子操作。因此,在不同的线程异步调用相同的矩阵是安全的操作。

ps: 当然还有很多操作矩阵的方法,如求逆矩阵(inv函数)、求转置矩阵(t函数)等等。。。。

4、成员变量

int cv::Mat::cols;     // 返回矩阵的列数 

int cv::Mat::rows      // 返回矩阵行数

uchar* cv::Mat::data   // 指向矩阵的数据单元的指针 
 
int cv::Mat::dims      // 返回矩阵维度,该维度≥2 

MatSize cv::Mat::size  // 返回矩阵大小

OpenCV的方法远不止这些,只是刚好用了一些,这里记录一下,方便以后温习。文章来源地址https://www.toymoban.com/news/detail-700205.html

到了这里,关于【OpenCV】浅谈 Mat 类的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 计算机毕设 python opencv 机器视觉图像拼接算法

    🔥 这两年开始毕业设计和毕业答辩的要求和难度不断提升,传统的毕设题目缺少创新和亮点,往往达不到毕业答辩的要求,这两年不断有学弟学妹告诉学长自己做的项目系统达不到老师的要求。 为了大家能够顺利以及最少的精力通过毕设,学长分享优质毕业设计项目,今天

    2024年02月07日
    浏览(59)
  • 计算机竞赛 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

    🔥 优质竞赛项目系列,今天要分享的是 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/postgraduate 物体检测就是对数字图像中一类特定的物体的

    2024年02月11日
    浏览(62)
  • 计算机视觉+深度学习+机器学习+opencv+目标检测跟踪(代码+视频)

    计算机视觉、深度学习和机器学习是当今最热门的技术,它们被广泛应用于各种领域,如自动驾驶、医学图像分析、安防监控等。而目标检测跟踪技术则是计算机视觉中的一个重要分支,它可以帮助我们在图像或视频中自动识别和跟踪特定的目标。 下面我们来一一介绍这些技

    2024年02月01日
    浏览(108)
  • 计算机竞赛 机器视觉人体跌倒检测系统 - opencv python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 机器视觉人体跌倒检测系统 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng-senior/

    2024年02月07日
    浏览(63)
  • 计算机竞赛 深度学习 机器视觉 人脸识别系统 - opencv python

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习 机器视觉 人脸识别系统 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:3分 🧿 更多资料, 项目分享: https://gitee.com/dancheng

    2024年02月07日
    浏览(83)
  • 计算机毕设 基于机器视觉的二维码识别检测 - opencv 二维码 识别检测 机器视觉

    今天学长向大家介绍一个机器视觉的毕设项目,二维码 / 条形码检测与识别 基于机器学习的二维码识别检测 - opencv 二维码 识别检测 机器视觉 物体检测就是对数字图像中一类特定的物体的位置进行自动检测。基本的检测框架有两种: 一种是以滑动窗口为单位对图像进行扫描

    2024年02月10日
    浏览(51)
  • 多目标跟踪算法 实时检测 - opencv 深度学习 机器视觉 计算机竞赛

    🔥 优质竞赛项目系列,今天要分享的是 🚩 深度学习多目标跟踪 实时检测 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:3分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/dancheng-sen

    2024年02月05日
    浏览(66)
  • 计算机竞赛 深度学习 opencv python 公式识别(图像识别 机器视觉)

    🔥 优质竞赛项目系列,今天要分享的是 🚩 基于深度学习的数学公式识别算法实现 该项目较为新颖,适合作为竞赛课题方向,学长非常推荐! 🥇学长这里给一个题目综合评分(每项满分5分) 难度系数:3分 工作量:4分 创新点:4分 🧿 更多资料, 项目分享: https://gitee.com/d

    2024年02月07日
    浏览(57)
  • Opencv C++图像处理:矩阵Mat + 随机数RNG + 计算耗时 + 鼠标事件

    数据类型 字节数 取值范围 bool型(布尔型) 1 [0 or 1] BOOL型(int型) 4 [TRUE or FALSE] sbyte型(有符号8位整数) 1 [128 ~ 127] bytet型(无符号8位整数) 8U 2 [0 ~ 255] short型(有符号16位整数) 16S 2 [-32,768 ~ 32,767] ushort型(无符号16位整数) 16U 2 [0 ~ 65,535] int型(有符号32位整数) 32S 4 [

    2024年02月03日
    浏览(53)
  • 实战指南:使用OpenCV 4.0+Python进行机器学习与计算机视觉

    💂 个人网站:【办公神器】【游戏大全】【神级源码资源网】 🤟 前端学习课程:👉【28个案例趣学前端】【400个JS面试题】 💅 寻找学习交流、摸鱼划水的小伙伴,请点击【摸鱼学习交流群】 计算机视觉和机器学习的融合为我们带来了前所未有的机会和挑战。从智能助手到

    2024年02月13日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包