Mat类

Mat类是OpenCV里广泛使用的一个类,主要用来作为存储图像的数据结构。

首先我们需要知道,OpenCV最早出现时其库是围绕C语言接口构建的。然后从OpenCV 2.0 开始引入c + + 接口。由于C++对C语言的兼容性,故而后面的版本可以兼容之前的版本,但反之则不行。

Mat类就是在2.0之后才有的,而在此之前,用来存储图像的是IplImage*CvMat,由于C语言的限制,这两者都是struct,里面只定义了一些变量而没有函数(虽然C语言在struct使用函数指针可以达到类似class的效果,可以实现在C语言的struct中加成员函数,但在C语言中这样做的情况很少)。这样如果要释放IplImage和CvMat变量中的内存也就需要调用相关的函数,而不能让其自动处理,如果程序员没有释放其内存就会造成内存泄漏。相比之下,Mat就不需要程序员手动去管理内存。

Mat本质上是由两个数据部分组成: 一个矩阵头和一个指针,该指针指向包含了像素值的矩阵。矩阵头的大小是恒定的,用来存放矩阵的尺寸、存储方法、存储地址等相关信息,其内存开销并不大。关键在于Mat中数据指针所指向的那个矩阵,该矩阵用来保存图片中所有的像素值,开销相对而言大非常多。所以Mat会尽量不去重复存储同样的图片数据矩阵。Mat采取的方法是:当新建一个Mat用于存储一个图片的时候,(在矩阵头放完图片的相关信息后)会新建一个矩阵的空间用来存放这些像素数据,然后Mat只需要将其数据指针指向这个矩阵即可。如果我们想要进行赋值或者初始化构造的操作的时候,只是让Mat2也指向了Mat1数据指针所指向的那个矩阵而已(这里可以看出是浅拷贝),此时存放具体像素数据的矩阵依旧只有一份。如果我们想要进行深拷贝则需要Mat2=Mat1.clone();

Mat的内存自动清理采用引用计数的机制来实现(其类似于STL中的智能指针share_ptr):即有一个计数器会标记指向该矩阵的Mat数据指针有多少个,如果是最后一个指向该矩阵的指针,那么当该指针离开该矩阵的时候,会释放该矩阵所占用的空间,避免内存泄漏。

 

重要的成员变量:

data

data是一个uchar型的指针,这就是那个传说中的指向数据矩阵的指针。

 

dims 

Mat矩阵的维度。若其指向的数据矩阵是一个二维矩阵,则dims=2,三维则dims=3。

rows

Mat矩阵的行数。

cols

Mat矩阵的列数。

以上这种类似于存储图像的矩阵的系统信息(列数、行数、维度等等)都归于之前所述的矩阵头部信息之列。

 

 

常用的构造方法:

Mat::Mat()

无参构造方法

 

Mat::Mat(int rows, int cols, int type)

创建行数为rows,列为cols,类型为type的Mat型变量(type如CV_8UC1等)。 
 

Mat::Mat(Size size, int type)

创建大小为size,类型为type的图像,这里Size类可以通过cv::Size sz( w, h );方式构造。
 

Mat::Mat(int rows, int cols, int type, const Scalar& s)

创建行数为 rows,列数为 cols,类型为 type 的图像,并将所有元素初始值赋为s 。Scalar则根据图像类型来选择变量个数,比如RGB图像则用Scalar(1,2,3)赋三个值使得B=1,G=2,R=3。
 

Mat::Mat(Size size, int type, const Scalar& s)

创建大小为 size,类型为 type 的图像,并将所有元素初始值赋为 s 。
 

Mat::Mat(const Mat& m)

利用另一个Mat对象对其初始化,但是两个变量共用一个图像的矩阵数据。
 

Mat::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP)

创建行数为 rows,列数为 cols,类型为 type 的图像,此构造函数不创建图像数据所需内存,而是直接使用 data 所指内存,图像的行步长由 step 指定 

 

Mat::Mat(Size size, int type, void* data, size_t step=AUTO_STEP)

创建大小为 size,类型为 type 的图像,此构造函数不创建图像数据所需 内存,而是直接使用 data 所指内存,图像的行步长由 step 指定 

 

Mat::Mat(const Mat& m, const Range& rowRange, const Range& colRange)

创建的新图像为 m 的一部分,具体的范围由 rowRange 和 colRange 指 定,此构造函数也不进行图像数据的复制操作,新图像与m共用图像数据 
 

Mat::Mat(const Mat& m, const Rect& roi)

创建的新图像为m的一部分,具体的范围roi指定,此构造函数也不进行图像数据的复制操作,新图像与m共用图像数据。
 

Mat常用的单个像素的读取方法:

1.动态地址计算

如果是灰度图可以

uchar value = grayim.at(i, j);

grayim.at(i, j) = 128;

RGB图像则可以

Vec3b pixel;

pixel[0] = 18;

pixel[1] = 28;

pixel[2] = 38;

colorim.at(i, j) = pixel;

 

2.迭代器操作方式

这里只放一下彩色图像的方式了

MatIterator_ it, itend;
for (it = outputImage.begin(), itend = outputImage.end(); it != itend; ++it) {
    //处理每个像素
    (*it)[0] = (*it)[0] / div * div + div / 2;
    (*it)[1] = (*it)[1] / div * div + div / 2;
    (*it)[2] = (*it)[2] / div * div + div / 2;
}

 

3.指针访问方式

for (int i = 0; i < rowNumber; i++)    //行循环

{

    uchar* data = outputImage.ptr(i);

    //ptr函数可以获取第i行首地址

    for (int j = 0; j < colNumber; j++)//列循环

    {

        data[j] = data[j] / div*div + div / 2;

    }

}

 

 

转载请标明出处,原文地址:https://blog.csdn.net/come_from_pluto

你可能感兴趣的:(OpenCV)