OpenCv2 学习笔记(1) Mat创建、复制、释放

2023-05-16

OpenCV和VS2013的安装图文教程网上有很多,建议安装好之后,用VS2013建立一个空工程,用属性管理器分别新建一个对应debug和release工程的props配置文件,以后直接根据工程需要添加对应配置文件,而不需要每次新建工程后填写引用目录、库目录、附加依赖项,减少重复工作。

(用WLW编辑,段间距有点大!)需要说明的是,本学习笔记不会按照先讲数据结构,再讲如何使用。与OpenCv1.x不用中,opencv2.x及3.x中用Mat代替了CvMat和IplImage。因此,对Mat的使用,会从一些例子给出一个直观的感受,之后再根据一些例子遇到新的东西就进行详细的讲解,遵循学习中遇到问题解决问题的方式。

为了使得Mat的输出更美观,自己写了一个Mat的输出;首先创建工程,cpp文件的主程序如下:

#include <opencv2/opencv.hpp>
#include <iostream>
 
using namespace cv;
using namespace std;  
 

void coutMat(const char *str, InputArray &_m) // _m可以是各种矩阵形式,包括vec、vector和表达式等。

{   //通过getMat()获取不同输入格式的Mat的数据,浅复制
    cout << str << endl << " " << _m.getMat() << endl << endl; 
}
 
void main()
{
    //编辑代码
    waitKet();         //避免命令行窗口一闪而过
}

1、Mat的创建、复制

/*
* Create Mat
*/
Mat M(2, 2, CV_8UC3, Scalar(0, 0, 255));   // 构造函数的一种
cout << "M=" << endl << " " << M << endl << endl;
 
Mat A;
M.copyTo(A);
 
M.release();
cout << A << endl;        // 释放不影响
 
 Mat B;
B = M.clone();
 
 M.release();
cout << "B=" << endl << " " << B << endl<<endl;    

Mat的一个构造函数 C++: Mat::Mat(int rows, int cols, int type, const Scalar& s) ,其中rows和cols是需要创建的矩阵的行数和列数,type是Mat的数据类型,s是Scalar类型的矩阵初值。

对于type,是基本数据类型,首先有枚举 enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 分别对应,8位无符号(uchar)、8位有符号(char)、16位无符号(ushort)、16位有符号(short)、32位有符号(int)、32位浮点(float)和64位双精度(double);其次 CV_8UC1、CV_16FC2、.. CV_64FC4等是多通道的类型,可以用CV_(深度)(类型)(通道数)描述, 例如本例中CV_8UC3,是指8位无符号3通道,其他类推。

对于s的Scalar类型,它的源头实际是一个4行1列的Mat,这里的Scalar(0,0,255),直接可以理解成M矩阵的每一个元素都是(0,0,255),当M看成图像,就是一个2x2的红色方块,Scalar有3个值,可以对应RGB色彩,通道顺序为(B,G,R)。那么,CV_8UC2,可以用Scalar(1,2)赋值,CV_64UC4可以用Scalar(0,0.1,0.08,100.1)赋值,其他类推。

Mat类的两个拷贝函数,copyTo()和clone(),都是进行深复制,也就是会另外开辟一个内存存储被复制的数据区域,对复制得到的新矩阵进行释放releas()不会影响原矩阵的数据(有其他方式会影响,后面遇到再讲)。这里的copyTo()和clone()区别在于,copyTo()可选一个参数掩膜mask,根据mask的值选择复制区域。

上面例子的结果如下:

image

 

2、Mat的释放

Mat mat1 = Mat::ones(1, 5, CV_32F);
Mat mat2 = mat1;                        // 仅创建一个mat2信息头, mat1,mat2 数据区的地址相同
Mat mat3 = Mat::zeros(1, 4, CV_32F);
mat2.release();          //  因为mat2是对mat1的引用,这里的mat2.release()只会清除mat2的信息头和数据指针
mat1.release();         //  mat1的数据区都会被释放,但是mat信息头数据还会保存(也就是还能继续被赋值)
cout << mat1 << endl;
cout << mat2 << endl;
cout << mat3 << endl << endl;
mat3.copyTo(mat1);// 拷贝会给mat1从新分配数据区域,其原来的数据区还会保留,即mat2的数据是原来mat1的数据,
//mat1 = mat3.clone();  // 最终结果是mat1和mat3的数据相同,但是数据存储空间不同,  mat2存储的是mat1最初的值
mat3.release();        // mat3的释放不会影响mat1
cout << mat1 << endl;
cout << mat2 << endl;
cout << mat3 << endl << endl;

有关注释读起来比较拗口,上面的例子最好调试下。总之,对于Mat的引用(也就是浅复制,只分配信息头,数据区共享)情况下的释放,只会清除本身的信息头和置零数据区指针,不会影响被赋值的矩阵。Mat有一个引用机制,有一个成员变量refcount,会自己根据被引用和释放的次数,自动管理内存,所以一般不需要用户自己去释放。对于创建类型的构造函数(深复制),那么会有属于自己的数据区,完全和被赋值的矩阵可以独立开。

3、Mat的复制和释放

Mat A = (Mat_<uchar>(5, 2) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10); //A为5x2的uchar类型矩阵,并被赋初值1-10
Mat B = A;        // B引用A,浅复制(仅创建信息头,数据指针指向A的数据区,没有数据的复制)
Mat C = B.row(3);   // 同样是引用,C指向B的4行
Mat D = B.clone();  // D是深复制B,实际是A的深复制。
B.row(4).copyTo(C); // B、C都是引用A,这里相当于是把A的第4行“7,8”两个数换成了第5行“9,10”
A = D;      //D是从B也就是A深度复制,这里A引用了D
B.release();// B是引用,浅复制,这里释放的B的信息头并将其将数据指针置为0
C = C.clone();    // 因为C是浅复制,进过clone()深度之,开辟了内存并完全复制了数据,是完全独立于A的。

这一个例子,可以更加深入的了解Mat的复制和释放机制,调试的时候可以看下各矩阵的refcount变量。下面的一个例子,copyTo()函数有第二个参数mask情况,代码和结果如下:

Mat A = (Mat_<uchar>(5, 2) << 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
Mat mask = (Mat_<uchar>(5, 2) << 0, 0, 1, 1, 0, 0, 0, 0, 1, 1); 
Mat C,D;
A.copyTo(C);      // 第二个参数为空,等效于A.copyTo(C,Mat());  
A.copyTo(D, mask);//mask必须和被复制矩阵大小相同 
coutMat("C = ", C);    //和C一样
coutMat("D = ", D); //D和C大小一样,但是只复制了第2、5行的数据,其他为0

image

4、其他

对于数学计算还有一些基本的构造函数,如Mat::eye()对角阵(当行、列不同时,主对角线为1)、Mat::ones()单位阵、Mat::zeros()零矩阵等。

用一个矩阵的一行复制到另外一行,不能通过直接复制,必须通过运算才行(运算的结果会返回一个实际的矩阵)。如矩阵mat的第1行复制到第2行,代码为 mat.row(1)=mat.row(0) 无效,但是 mat.row(1)=mat.row(0)+0; 或者 mat.row(1)=mat.row(0)+mat.row(2); 都是有效的。

 

总结

对于Mat一般只需要区什么是浅复制和深复制即可,何时需要就直接创建,释放可以交给OpenCv管理。另外没有提到的是,当Mat直接被另外一个大小不同的矩阵深幅值时,Mat会先被释放再被复制,不需要同OpenCv1.X中先释放再指定需要的size才能被再次使用。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

OpenCv2 学习笔记(1) Mat创建、复制、释放 的相关文章

  • C++常用类型转换

    char是C语言标准数据类型 xff0c 字符型 xff0c 至于由几个字节组成通常由编译器决定 xff0c 一般一个字节 Windows为了消除各编译器的差别 xff0c 重新定义了一些数据类型 CHAR为单字节字符 还有个WCHAR为U
  • C++在dll中获取自身路径(非exe调用路径)

    include 34 stdafx h 34 include lt fstream gt include lt iostream gt include lt windows h gt using namespace std HMODULE
  • MFC/VC++中怎样设置位图按钮并且位图不会覆盖文字——–位图按钮

    1 第一次尝试 设置 IDC BUTTON3按钮风格的bitmap为true 在OnInitialDilog中 xff1a CButton cbpTest 61 NULL HINSTANCE hInstance 61 AfxGetResou
  • MFC 之 重绘按键Cbutton

    上次我们学习了如何美化对话框的界面 xff0c 这次我们为上次的对话框添加两个按钮 xff0c 一个是关闭按钮 xff0c 另一个是最小化按钮 xff0c 好 xff0c 现在我们先看一下效果 xff1a 是不是很难看 xff0c 因为我们
  • VC的MFC中重绘函数的使用总结(整理)

    原文网址 xff1a http www cnblogs com x8023z archive 2008 12 09 mfc33 html 在刷新窗口时经常要调用重绘函数 MFC提供了三个函数用于窗口重绘 InvalidateRect amp
  • DrawItem

    原文链接 http blog csdn net jiftlixu article details 4893505 今天从CButton派生了一个类CUIButton xff0c 主要用于自绘 xff0c 按照基本的流程 xff0c 重写Dr
  • C/C++报错:全局变量重定义或是多次定义

    很多人可能直接把全局变量写进 h文件 xff0c 然后用多个文件包含这个头文件 xff0c 编译时就会报错 xff1a 变量重定义 头文件的作用就是要给外部提供接口使用的 xff0c 所以请记住 xff0c 只在 h中做声明 xff0c 在
  • C++ 包含目录、库目录、附加依赖项总结

    在使用opencv库 xff0c 以及其他库的时候 xff0c 经常会需要添加包含目录 库目录 附加依赖项等 现做一个总结吧 1 包含目录 是 h的头文件所在的目录 xff0c 如果没有正确包含目录 xff0c 代码中会出现红色的警告 xf
  • c++设置不适用预编译头

    编译器提示在末尾是否忘了添加stdafx h 可右键相应的 cpp文件 xff0c 设置c 43 43 设置不适用预编译头
  • Linux高级字符设备之Poll操作

    在用户程序中 xff0c select 和poll 也是与设备阻塞与非阻塞访问息息相关的 xff0c 使用非阻塞I O的应用程序通常会使用select和poll系统调用查询是否可对设备进行无阻塞的访问 select系统调用最终会引发设备驱动
  • C++中关于[]静态数组和new分配的动态数组的区别分析

    一 静态数据及动态数组的创建 静态数据 xff1a int a 10 xff1b int a 61 1 2 3 数组的长度必须为常量 动态数组 xff1a int len int a 61 new int len delete a 数组的大
  • MFC中将CBitmap画到cdc上

    取Picture矩形和它的DC CRect rect CWnd pWnd 61 GetDlgItem IDC PICTURE LINK pWnd gt GetClientRect rect CDC pDC 61 pWnd gt GetDC
  • MFC中获取任务栏大小

    MFC怎么获得当前屏幕大小 你可以这样 HWND hwnd 61 GetDesktopWindow RECT rect GetClientRect hwnd amp rect 可以得到桌面大小 还有就是上面所说的 int nScreenWi
  • MFC中OnCtlColor的用法(改变控件颜色)

    HBRUSH CMFCApplication1Dlg OnCtlColor CDC pDC CWnd pWnd UINT nCtlColor HBRUSH hbr 61 CDialogEx OnCtlColor pDC pWnd nCtlC
  • MFC与OpenCv中的图片转换实例

    include 34 AnalysisManager h 34 IplImage GetFontDiscerImage char sourcePath 打开要识别字符的图像 IplImage image 61 cvLoadImage sou
  • mfc中主窗体显示(任务栏上方显示)

    int sx 61 GetSystemMetrics SM CXSCREEN 获得屏幕的大小 宽 int sy 61 GetSystemMetrics SM CYSCREEN 获得高 int st 61 GetSystemMetrics S
  • MFC改变对话框背景图片实例

    TODO 在此添加消息处理程序代码和 或调用默认值 CPaintDC dc this device context for painting CRect rect GetClientRect amp rect 获取对话框长宽 CDC dcB
  • 浅谈MFC中BitBlt与StretchDIBits的区别

    一 基础知识 1 BitBlt BitBlt 用于从原设备中复制位图到目标设备 xff0c 语法格式如下 xff1a BOOL BitBlt HDC hdcDest handle to destination DC int nXDest 目
  • 关于HBITMAP,CBITMAP,BITMAP的转换以及图像显示的一点归纳

    OK xff0c 在上一篇文章中我提到了VC6和VS的差别 xff0c 在VC6中我们只能依赖于CBITMAP HBITMAP以及BITMAP之间的转化关系 xff0c 而在VS中 xff0c 我们用CIMAGE类就可以全部搞定 xff0c
  • CDC中图片绘制到控件上

    CDC中 CDC gt StretchBlt xff08 int x xff0c int y xff0c int nWidth xff0c int nHeight xff0c CDC pSrcDC int xSrc int ySrc int

随机推荐

  • ESP8266/ESP32+OLED12864简单WiFi扫描器 支持OTA

    功能描述 OLED显示SSID 全中文界面 支持中文SSID Arduino OTA支持 硬件准备 ESP8266 NodeMCU WiFi ESP32 WIFI 43 BLE 43 OLED开发板 OLED控制芯片 SSD1315兼容SS
  • C#用到windows 消息列表Message类MSG的id代号

    C Constants private const UInt32 WM ACTIVATE 61 0x0006 private const UInt32 WM ACTIVATEAPP 61 0x001C private const UInt3
  • C++ Map用法详解

    用法汇总 insert 插入一个元素 size 获得map中元素的个数 max size 获得map所能容纳的元素个数 count 判断是否存在某个key xff0c 存在为返回1 find 查找某个key erase 删除指定的元素 cl
  • C++中vector作为参数的三种传参方式

    此文章转载自 xff1a http www cnblogs com xiaoxi666 p 6843211 html c 43 43 中常用的vector容器作为参数时 xff0c 有三种传参方式 xff0c 分别如下 xff08 为说明问
  • OpenCV中Mat总结

    一 数字图像存储概述 数字图像存储时 xff0c 我们存储的是图像每个像素点的数值 xff0c 对应的是一个数字矩阵 二 Mat的存储 1 OpenCV1基于C接口定义的图像存储格式IplImage xff0c 直接暴露内存 xff0c 如
  • opencv----(1) mat最好用,和IplImage,cvmat 比较

    学习了几天 xff0c 发现mat比IplImage cvmat 好用太多了 不知道确切的原文出处 xff0c 我是转自新浪的一篇博文 xff1a http blog sina com cn s blog 534497fd01015k7z
  • OpenCV学习笔记之 ( 三 ) MFC显示Mat图片

    以下步骤参考以下链接 http blog csdn net dcrmg article details 51913160 原理及详解见上链接 下面只讲步骤 一 打开VS2010 xff0c 建立对话框的项目 二 建立 PictureCont
  • 彻底解决显示Opencv中Mat图像到Mfc窗口问题

    第一步 xff0c 转换格式前预先获得待显示控件的大小 xff0c 若相等则不做处理 xff0c 若不等则首先改变Mat图像大小 xff0c 再进行转换 CRect rect GetDlgItem IDC STATIC SRC gt Get
  • 在MFC中显示cv::Mat

    BOOL DrawMat CDC pDC cv Mat amp img CRect amp rect if img empty img depth 61 CV 8U img channels 61 3 return FALSE BITMAP
  • 在MFC图像控件上显示opencv Mat格式图片

    显示opencv图片格式Mat到图像控件vIDC上 vMat xff1a 图像Mat vIDC xff1a 图像控件ID void CDLFaceDlg showMat Mat vMat int vIDC if vMat empty ret
  • 在OpenCV中将cv::Mat绘制到MFC的视图中

    毕设时遇到了一个问题 xff0c 不能在MFC中显示由GrabCut抠出来的图 经一番折腾发现 xff1a 在OpenCV中如果图像最初是Mat类型的话 xff0c 就不能通过转换为IplImage xff0c 再转换为CvvImage来显
  • 【AutoLisp】AutoLisp中的DCL界面应用基础

    目录 01 DCL的作用 01 01 DCL介绍 01 02 DCL对话框成员 01 标准DCL对象家族 02 装饰DCL对象家族 03 集群DCL对象家族 04 整合DCL对象家族 02 DCL的加载 03 DCL的规则 04 DCL对话
  • 在MFC的picture控件中如何显示Mat图

    首先 xff0c 要进行输入检查 xff0c 看Mat数据是否是有效的 xff0c 如下图中所示 定义位图数据结构 xff0c 用以方便在图形设备接口 GraphicsDeviceInterface 上显示 xff0c 也就是windows
  • MFC+OPENCV+显示MAT类型图像

    MFC显示图像到界面 xff0c 可以用链接中的DrawMatToPic xff0c 有时会出现IplImage 类型转换问题 xff0c 因为用opencv做后续图像处理 xff0c 所以统一使用Mat类型 xff0c 可以showMat
  • CvMat、Mat、IplImage之间的转换详解及实例

    IplImage xff1a 在OpenCV中IplImage是表示一个图像的结构体 xff0c 也是从OpenCV1 0到目前最为重要的一个结构 xff1b 在之前的图像表示用IplImage xff0c 而且之前的OpenCV是用C语言
  • RGB和RGBQUAD的区别

    RGB和RGBQUAD的区别 昨天的晚上 为一个问题困扰了很长时间 几乎整个晚上都在弄一个小bug 感觉没有问题 但就是效果不理想 几次三番 查来查去 我想实现的功能是 生成一张图 图上有字 这张图是以一张指定的位图为背景的 我使用 COL
  • BITMAPINFO结构

    BITMAPINFO结构 BITMAPINFO结构具有如下形式 xff1a typedef struct tagBITMAPINFO BITMAPINFOHEADER bmiHeader RGBQUAD bmiColors 1 BITMAP
  • OpenCV中的cv::String和CString互相转换

    请注意是cv String xff0c 而不是std string xff0c 第一个字母是大写的 基本上CString转cv String网上都能查到 xff0c 而cv String转CString没有人提到 1 CString gt
  • MFC——文件打开和保存对话框(CFileDialog)

    最近要做一个文件打开和保存的对话框 xff0c 现将相关的代码记录如下 xff0c 用以备忘 xff01 所用控件 xff1a 2个静态标签 Static Text xff1a 用以显示功能标签 xff1b 2个文本框 Edit xff1a
  • OpenCv2 学习笔记(1) Mat创建、复制、释放

    OpenCV和VS2013的安装图文教程网上有很多 xff0c 建议安装好之后 xff0c 用VS2013建立一个空工程 xff0c 用属性管理器分别新建一个对应debug和release工程的props配置文件 xff0c 以后直接根据工