OpenCV中的Mat类

OpenCV Mat类

OpenCV 自 2001 年出现以来。在那些日子里库是围绕C接口构建的。在那些日子里,他们使用名为IplImage C 的结构在内存中存储图像。 使用这个结构的问题是将 C 语言的所有负面效果都摆到了桌面上。最大的问题是手动管理。它是建立在用户来负责处理内存分配和解除分配的假设之上的。当程序规模较小时,这是没有问题的,一旦代码基开始变得越来越大它将会越来越难处理。

OpenCV在其2.0 版本引入一个新的c + + 接口,某种程度上,不需要手动内存管理就可以让你的代码简洁。C + + 接口的唯一主要缺点在于,目前许多嵌入式的开发系统支持仅 C。

需要知道的关于Mat的第一件事是不需要为一个Mat手动分配其大小,并且当你不需要它的时候也不再需要手动释放它。此外,如果传递一个已存在Mat对象,它已经为矩阵分配所需的空间,这段空间将被重用。也就是说我们在任何时候只使用与我们执行任务时所必须多的内存一样多的内存。

Mat本质
Mat是由两个数据部分组成的类: 一个(包含信息有矩阵的大小,用于存储的方法,矩阵存储的地址等的) 矩阵头和一个指向包含了像素值的矩阵(可根据选择用于存储的方法采用任何维度存储数据)的指针。
矩阵头部的大小是恒定的。然而,矩阵本身的大小因图像的不同而不同,通常是较大的数量级。因此,当你在您的程序中传递图像并在有些时候创建图像副本您需要花费很大的代价生成图像矩阵本身,而不是图像的头部。OpenCV 是图像处理库,它包含大量的图像处理函数,所以尽可能减少不必要的图像的拷贝操作,以提高程序运行速度。

为了解决这一问题 OpenCV 使用引用计数系统。其思想是Mat的每个对象具有其自己的头,但可能他们通过让他们矩阵指针指向同一地址的两个实例之间共享该矩阵。此外,拷贝运算符将只能复制矩阵头部,也还将复制指针到大型矩阵,但不是矩阵本身。

Mat A, C; //仅创建了矩阵头部

A = imread(argv[1], CV_LOAD_IMAGE_COLOR); //在此我们知道使用的方法(分配矩阵)

Mat B(A); //使用拷贝构造函数

C = A; //赋值运算符

上文中的所有对象,以相同的单个数据矩阵的结束点。他们头不同,但是使用的其中任何一个对矩阵进行任何修改,也将影响所有其他的。在实践中的不同对象只是提供相同的底层数据不同的访问方法,然而,它们的头部是不同的。真正有趣的部分是您可以创建仅指向完整数据的一小部分的头。例如,要在图像中创建兴趣区域 ( ROI) 您只需创建一个新头设置新边界:

Mat D (A, Rect(10, 10, 100, 100) ); // 用矩形界定

Mat E = A(Range:all(), Range(1,3)); // 用行和列来界定

现在,你可能会问是否矩阵的本身可以属于多个Mat对象在不再需要时负责清理数据。简短的回答是:最后一个使用它的对象。这对于使用引用计数的机制,每当有人复制Mat对象的头,矩阵的计数器被增加。每当一个头被清除,此计数器被下调。当该计数器变为零,矩阵也就被释放了。因为有时会仍然也要复制矩阵的本身,存在着 clone() 或 copyTo() 函数。

Mat B = A.clone();
A.copyTo(B);

注意
• 输出图像分配 OpenCV 功能是自动 (除非另行指定,否则)。

• 用c + + OpenCV的接口就无需考虑内存释放。

• 赋值运算符和复制构造函数 (构造函数)只复制头。

• 使用clone () 或copyTo () 函数将复制的图像的基础矩阵。

存储方法
这是关于你是如何存储的像素值。您可以选择的颜色空间和使用的数据类型。色彩空间是指我们如何结合为了代码指定的颜色的颜色分量。最简单的是灰色的规模。在这里我们所掌握的颜色是黑色和白色。组合的这些让我们能创造很多的灰度级。

对于彩色的方法,我们有很多方法可供选择。不过,每一就是将他们拆解成三个或四个基本组成部分,这些部分就会组合给所有其他的方法。最受欢迎的这一个 RGB,主要是因为这也是我们的眼睛如何建立中我们的眼睛的颜色。其基准的颜色是红、 绿、 蓝。编写代码的一种颜色的透明度有时第四个元素: 添加 alpha (A)。

各自的优势

• RGB 是最常见的是我们的眼睛使用类似的事情,我们显示系统还撰写使用这些颜色。

· 单纯疱疹和合肥分解颜色到他们的色相、 饱和度和亮度值/组件,这是我们来描述颜色更自然的方式。您使用,例如可驳回的最后一个组件,使

你不那么明智的输入图像的光照条件的算法。

• YCrCb 使用流行的 JPEG 图像格式。

• CIE LAB 色空间是均匀颜色空间,
目前最受广用的测色系统。以明度L和色度坐标a、b来表示颜色在色空间中的位置。l表示颜色的明度, a* 正值表示偏红,负值表示偏绿;b*正值表示偏黄,负值表示偏蓝

显式创建Mat对象

•由IplImage创建一个头:

IplImage* img = cvLoadImage("greatwave.png", 1);

Mat mtx(img); 	// 转换 IplImage*-> Mat

• Create()函数:

M.create(4,4, CV_8UC(2));

• MATLAB风格的初始化函数:zeros(), ones(),eyes()

Mat E = Mat::eye(4, 4, CV_64F);   //对角阵

Mat O = Mat::ones(2, 2, CV_32F);    //全为1

Mat Z = Mat::zeros(3,3, CV_8UC1);   //全为零

Mat C = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);   //指定
 
Mat RowClone = C.row(1).clone();

Mat R = Mat(3, 2, CV_8UC3);
randu(R, Scalar::all(0), Scalar::all(255));  //randu()函数产生的随机值来填充矩阵,上限和下限 

Mat函数和方法

  • Mat::row
    创建一个指定行数的矩阵头。.

  • Mat::col
    创建一个具有指定了矩阵头中列数这个参数的矩阵。

  • Mat::rowRange
    为指定的行span创建一个新的矩阵头。

  • Mat::colRange
    为指定的行span创建一个矩阵头。

  • Mat::diag
    提取或创建矩阵对角线。

  • Mat::clone
    创建一个数组及其基础数据的完整副本。

  • Mat::copyTo
    把矩阵复制到另一个矩阵中。

  • Mat::convertTo
    在缩放或不缩放的情况下转换为另一种数据类型。

  • Mat::assignTo
    提供了一个convertTo的功能形式。

  • Mat::setTo
    将阵列中所有的或部分的元素设置为指定的值。

  • Mat::reshape

  • Mat::t
    转置矩阵。.

  • Mat::inv
    反转矩阵
    method –
    – DECOMP_LU是 LU 分解一定不能是单数的。
    – DECOMP_CHOLESKY 是 Cholesky LLT只适用于对称正矩阵的分解。该类型在处理大的矩阵时的速度是LU的两倍左右。
    – DECOMP_SVD是 SVD 分解。如果矩阵是单数或甚至不是2维,函数就会计算伪反转矩阵。
    该方法执行矩阵的反转矩阵表达。这意味着该方法返回一个临时矩阵反转对象并可进一步用于更复杂的矩阵表达式的中或分配给一个矩阵。

  • Mat::mul
    执行两个矩阵按元素相乘或这两个矩阵的除法。

  • Mat::cross
    计算3元素向量的一个叉乘积。

该方法计算了两个3元素向量的叉乘的积被操作向量必须是3元素浮点型的具有相同形状和尺寸的向量。结果也是一语被操作对象的具有相同形状和大小的浮点型3元素向量。

  • Mat::dot
    计算两向量的点乘。

方法计算两个矩阵的点积。如果矩阵不单列或单行的向量,用顶部到底部从左到右扫描次序将它们视为 1 D向量。这些向量必须具有相同的大小和类型。如果矩阵有多个通道,从所有通道得到的点积会被加在一起。

  • Mat::addref
    计数器参考。
void Mat::addref()

该方法递增与矩阵数据关联的引用计数。如果矩阵头指向外部的数据集(见 Mat::Mat()),则引用计数为 NULL,并且该方法在这种情况下不起作用。通常情况下,为避免内存泄漏,不应显式调用该方法。它是由该矩阵赋值运算符隐式调用。在支持的它平台上,引用计数器递增是一个原子操作。因此,对相同的矩阵,在不同的线程异步操作是安全的。

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

void Mat::release()

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

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

  • Mat::resize
    更改矩阵的行数。

  • Mat::reserve
    保留一定数量的行的空间。

  • Mat::push_back
    将元素添加到矩阵的底部。

  • Mat::pop_back
    从底部的列表中删除元素。

  • Mat::locateROI
    父矩阵内定位矩阵头。

  • Mat::adjustROI
    调整子阵大小及其在父矩阵中的位置。

  • A.adjustROI(2, 2, 2,2);

在此示例中,每个方向 4 元素增加矩阵大小。矩阵向左侧和上侧分别平移2 个元素,这会产生5 x 5 内核的滤镜所需的所有像素。 确保 adjustROI 不超出父矩阵边界。

  • Mat::operator()
    提取矩形子阵,该运算符为*this的子数组创建新的头。他们是Mat::row()、 Mat::col()、 Mat::rowRange(),和Mat::colRange()最普遍的形式。
Mat::operator CvMat

创建矩阵 CvMat 头。

Mat::operator IplImage
创建IplImage矩阵头。

Mat::operator IplImage() const

运算符创建矩阵 IplImage 头,而不复制的基础数据。您应该确保使用IplImage头时不释放原矩阵。与Mat::operatorCvMat类似,该运算符在OpenCV新旧API混用中很有用。

Mat::total
返回数组元素的总数。

  • Mat::isContinuous
    返回矩阵是否连续。

  • Mat::elemSize
    返回矩阵元素大小 (以字节为单位)。

  • Mat::elemSize1
    以字节为单位返回每个矩阵元素通道的大小。

Mat::step1
返回矩阵归一化迈出的一步。

 size_t const Mat::step1()

该方法返回以矩阵的step除以Mat::elemSize1()。它对快速访问任意矩阵元素很有用。

  • Mat::ptr
    返回指定矩阵行的指针。

  • Mat::at
    返回对指定数组元素的引用。

  • Mat::begin
    返回矩阵迭代器,并将其设置为第一矩阵元

  • Mat::end
    返回矩阵迭代器,并将其设置为 最后元素之后(after-last)的矩阵元。
    该方法返回矩阵只读或读写的迭代器,设置为紧随最后一个矩阵元素的点。

  • 0
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值