认识OpenCV中的Mat容器

1.认识Mat

Mat最大的优势跟STL很相似,都是对内存进行动态的管理,不需要之前用户手动的管理内存,所以在图像处理中,我强烈向大家推荐Mat。

Mat这个类有两部分数据。一个是matrix header,这部分的大小是固定的,包含矩阵的大小,存储的方式,矩阵存储的地址等等。另一个部分是一个指向矩阵包含像素值的指针。

2.注意深拷贝与浅拷贝问题

<code>Mat A, C; // creates just the header parts
A = imread(argv[1], CV_LOAD_IMAGE_COLOR); // here we’ll know the method used (allocate matrix)
Mat B(A); // Use the copy constructor
C = A; // Assignment operator/<code>

需要注意的是,copy这样的操作只是copy了矩阵的matrix header和那个指针,而不是矩阵的本身,也就意味着两个矩阵的数据指针指向的是同一个地址,需要开发者格外注意。比如上面这段程序,A、B、C指向的是同一块数据,他们的header不同,但对于A的操作同样也影响着B、C的结果。刚刚提高了内存自动释放的问题,那么当我不再使用A的时候就把内存释放了,那时候再操作B和C岂不是很危险。不用担心,OpenCV的大神为我们已经考虑了这个问题,是在最后一个Mat不再使用的时候才会释放内存,咱们就放心用就行了。如果想建立互不影响的Mat,是真正的复制操作,需要使用函数clone()或者copyTo()。

3.返回值及其含义

说到数据的存储,这一直就是一个值得关注的问题,Mat_<uchar>对应的是CV_8U,Mat_<uchar>对应的是CV_8U,Mat_<char>对应的是CV_8S,Mat_

对应的是CV_32S,Mat_<float>对应的是CV_32F,Mat_<double>对应的是CV_64F,对应的数据深度如下:/<double>/<float>/<char>/<uchar>/<uchar>

认识OpenCV中的Mat容器

摘自官方文档

4.应用举例

我分别从Python、Numpy、OpenCV和C++风格分别输出Mat容器。

<code>//--------------------------------------【程序说明】-------------------------------------------
//\t\t程序描述:基础图像容器Mat类的使用
//\t\t开发测试所用操作系统: Windows 10 64bit
//\t\t开发测试所用IDE版本:Visual Studio 2017
//\t\t开发测试所用OpenCV版本:\t3.4
//\t\t2020年3月 Created by @DL小宝
//\t\t2020年3月 Revised by @DL小宝
//------------------------------------------------------------------------------------------------

//---------------------------------【头文件、命名空间包含部分】---------------------------
// 描述:包含程序所使用的头文件和命名空间
//-----------------------------------------------------------------------------------------------
#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;

//-----------------------------【ShowHelpText( )函数】--------------------------------------
//\t\t描述:输出帮助信息
//-------------------------------------------------------------------------------------------------
static void ShowHelpText()
{
\t//输出欢迎信息和OpenCV版本
\tprintf("\\n\\n\\t\\t\\t 当前使用的OpenCV版本为:" CV_VERSION);
\tprintf("\\n\\n ----------------------------------------------------------------------------\\n");

\t//输出一些帮助信息

\tprintf("\\n\\n\\n\\t欢迎来到【基本图像容器-Mat类】示例程序~\\n\\n");
\tprintf("\\n\\n\\t程序说明:\\n\\n\\t此示例程序用于演示Mat类的格式化输出功能,输出风格可为:");
\tprintf("\\n\\n\\n\\t【1】OpenCV默认风格");
\tprintf("\\n\\n\\t【2】Python风格");
\tprintf("\\n\\n\\t【3】逗号分隔风格");
\tprintf("\\n\\n\\t【4】Numpy风格");
\tprintf("\\n\\n\\t【5】C++语言风格\\n\\n");
\tprintf("\\n --------------------------------------------------------------------------\\n");
}

//--------------------------------------【main( )函数】-----------------------------------------
// 描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int, char**)
{
\t//改变控制台的前景色和背景色
\tsystem("color 8F");
\t//显示帮助文字
\tShowHelpText();
\tMat I = Mat::eye(4, 4, CV_64F);
\tI.at<double>(1, 1) = CV_PI;
\tcout << "\\nI = " << I << ";\\n" << endl;

\tMat r = Mat(10, 3, CV_8UC3);
\trandu(r, Scalar::all(0), Scalar::all(255));

\t//此段代码的OpenCV3版为:
\tcout << "r (OpenCV默认风格) = " << r << ";" << endl << endl;
\tcout << "r (Python风格) = " << format(r, Formatter::FMT_PYTHON) << ";" << endl << endl;
\tcout << "r (Numpy风格) = " << format(r, Formatter::FMT_NUMPY) << ";" << endl << endl;
\tcout << "r (逗号分隔风格) = " << format(r, Formatter::FMT_CSV) << ";" << endl << endl;
\tcout << "r (C语言风格) = " << format(r, Formatter::FMT_C) << ";" << endl << endl;


\tPoint2f p(6, 2);
\tcout << "【2维点】p = " << p << ";\\n" << endl;


\tPoint3f p3f(8, 2, 0);
\tcout << "【3维点】p3f = " << p3f << ";\\n" << endl;

\tvector<float> v;
\tv.push_back(3);
\tv.push_back(5);
\tv.push_back(7);

\tcout << "【基于Mat的vector】shortvec = " << Mat(v) << ";\\n" << endl;

\tvector<point2f> points(20);
\tfor (size_t i = 0; i < points.size(); ++i)
\t\tpoints[i] = Point2f((float)(i * 5), (float)(i % 7));

\tcout << "【二维点向量】points = " << points << ";";
\tgetchar();//按任意键退出
\treturn 0;
}/<point2f>/<float>/<double>/<iostream>/<code>



分享到:


相關文章: