Mat 的介绍和使用

Mat 的介绍


cv::Mat 是 OpenCv 中非常重要的一个类,它提供了一种自动化的方式来管理图片的加载、操作和销毁等。加载图片时,它会自动申请内存,根据实际情况自动释放该内存。
cv::Mat 有两个必不可少的组成部分:信息头数据块

  • 信息头:包含了矩阵的属性信息:矩阵尺寸、通道数量、数据类型等;
  • 数据块:包含了图像中所有像素的值。信息头有一个指向数据块的指针;
    cv::Mat 有一个很重要的属性:即只有在明确要求的情况下,内存块才会被复制。拷贝构造函数只是复制了 cv::Mat信息头,因此会多个对象指向同一个数据块,这种内存管理模式可以提高程序的运行效率,避免内存泄漏 。以下操作只复制了信息头
Mat A,C;// 仅仅创建信息头
A = imread("bird.jpg", CV_LOAD_IMAGE_COLOR); // 为数据块开辟内存
C = A; // 赋值运算
Mat D(A, Rect(10, 10, 100, 100)); // 使用矩形界定 ROI 区域
Mat E = A(Range::all(), Range(1, 3)); // 使用行和列来界定 ROI 区域

以上代码中所有的 Mat 对象拥有独自的 信息头,但都指向相同的 数据块。不同的对象只是以不同的方式访问同一块 数据块
可能会存在一个疑问?如果矩阵属于多个 Mat 对象,那么当不再需要它时,谁来负责清理呢?–最后一个使用它的对象负责清理。OpenCv 使用了引用计数机制。当我们复制一个 Mat 对象的信息头时,都会增加该矩阵的引用次数;反之,当一个头被释放时,这个计数就会减一;当这一数据块计数数值为零时,数据块内存会被自动清除。

但是,有的时候我们也想复制 数据块,该怎么做呢?可以使用 clone()copyTo() 函数,如下所示:

Mat F = A.clone();
Mat G;
A.copyTo(G);

此时改变 F 和 G 都不会影响 A 的 数据块


创建 Mat 对象


Mat 不但是一个非常有用的容器类,同时也是一个通用的矩阵类,我们可以用它来创建和操作多维矩阵

使用 Mat() 构造函数

使用 Mat 构造函数,如下所示:

cv::Mat M(2, 2, CV_8UC3,Scalar(0, 0, 255))
std::cout << "M = " << endl << " " << M << endl;

结构如图所示:

在这里插入图片描述

上述构造函数的原型如下:

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

具体参数含义如下:

  • rows:二维数组的行数;
  • cols:二维数组的列数;
  • type:二维数组的数据类型,其格式为:CV_[位数][带符号与否][类型前缀]C[通道数],常见的形式为:
    • CV_8UC3:表示 8 位无符号类型,每个元素由三个通道组成;
    • CV_8UC1:表示 8 位无符号类型,每个元素由三个通道组成;
    • CV_32FC2:表示 32 位单精度浮点类型,每个元素由两个通道组成;
    • CV_64FC4:表示 64 位双精度浮点类型,每个元素由四个通道组成;
  • s:初始化矩阵每一个元素的值。Scalar 是 Short 类型的向量,用来表示颜色;

创建多维度矩阵

样例如下:

/* create a 10 x 10 8-bit array*/
 /*
 int sz[2] = {10, 10};
 cv::Mat M(2, sz, CV_8U, cv::Scalar::all(1.0));
 std::cout << "M = " << std::endl << " " << M << std::endl << std::endl;

结果如下图所示:

在这里插入图片描述


利用 Create 函数进行初始化

使用样例如下:

/* 2. 创建多维度矩阵*/
 /* create a 10 x 10 8-bit array*/
 int sz[2] = {10, 10};
 cv::Mat M(2, sz, CV_8U, cv::Scalar::all(1.0));
 std::cout << "M = " << std::endl << " " << M << std::endl << std::endl;

 /* 3. 利用Create()函数进行初始化*/
 // and now turn M to a 3x4 5-channel 8-bit matrix.
 // The old content will be deallocated
 M.create(3, 4, CV_8UC(5));
 std::cout << "M = " << std::endl << " " << M << std::endl << std::endl;

结果如下图所示:

在这里插入图片描述

档要改变矩阵尺寸的时候,可以使用 `Create()` 函数,该函数会释放以前的空间,重新分配指定的空间给 Mat 对象;使用该函数不能为矩阵设置初始值。如果重新分配的矩阵大小与原矩阵一样,则不发挥作用。

采用 MatIab 式的初始化方式

采用Matlab形式的初始化方式:zeros(),ones(),eyes()。使用以下方式指定尺寸和数据类型:

cv::Mat E = cv::Mat::eye(4, 4, CV_64F);
 std::cout << "E = " << std::endl << " " << E << std::endl << std::endl;

 cv::Mat O = cv::Mat::ones(2, 2, CV_32F);
 std::cout << "O = " << std::endl << " " << O << std::endl << std::endl;
	
 cv::Mat Z = cv::Mat::zeros(3, 3, CV_8UC1);
 std::cout << "Z = " << std::endl << " " << Z << std::endl << std::endl;

结果如下所示:

在这里插入图片描述


小矩阵初始化

当要创建小矩阵时,可以采用如下形式:

/* 5. 小矩阵初始化*/
 cv::Mat C = (cv::Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
 std::cout << "C = " << std::endl << " " << C << std::endl << std::endl;

 double m[3][3] = { {1.0, 2.0, 3.0}, {4.0, 5.0, 6.0}, {7.0, 8.0, 9.0} };
 cv::Mat M = cv::Mat(3, 3, CV_64F, m);
 std::cout << "M = " << std::endl << " " << M << std::endl << std::endl;

结果如下:

在这里插入图片描述


用已存在的对象创建一个新的信息头

主要利用成员函数 clone()copyTo() 为一个已存在的 Mat 对象创建一个新的信息头,示例代码如下:

/* 6. 用已存在的对象创建一个新的信息头*/
cv::Mat C = (cv::Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
 cv::Mat RowClone1 = C.row(1).clone();
 std::cout << "RowClone1 = " << std::endl << " " << RowClone1 << std::endl << std::endl;

 cv::Mat RowClone2;
 C.row(1).copyTo(RowClone2);
 std::cout << "RowClone2 = " << std::endl << " " << RowClone2 << std::endl << std::endl;

上述代码的运行结果如下所示:

在这里插入图片描述

  • 1
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值