OpenCV学习笔记【三】基础图像容器Mat

Mat是一个类,有两个数据部分组成:矩阵头(包含矩阵尺寸、存储方法、存储地址等信息)和一个指向存储所有像素值的矩阵(根据所选存储方法的不同,矩阵可以是不同的维数)的指针。矩阵头的尺寸是一个常数值,但矩阵本身尺寸会依图像的不同而不同,通常比矩阵头的尺寸大数个数量级。因此当程序中传递图像并创建副本时,大的开销是由矩阵造成的,而不是信息头。为了解决这个问题,OpenCV使用了引用计数机制。其思路是让每个Mat对象有自己的信息头,但共享一个矩阵。这通过让矩阵指针指向同一地址而实现。而拷贝函数则只复制信息头和矩阵指针,而不是复制矩阵。

Mat A,C;//仅创建信息头部分
A = imread("1.jpg",CV_LOAD_IMAGE_COLOR);//这里矩阵开辟内存
Mat B(A);//使用拷贝构造函数
C=A;//赋值运算符

以上代码的所有Mat对象最终都指向同一个也是唯一 一个数据矩阵。虽然它们的信息头不同,但通过任何一个对象所做的改变也会影响其他对象。实际上,不同的对象只是访问相同数据的不同途径而已。这里还要提及一个比较帮的功能:我们可以创建只引用部分数据的信息头。比如想要创建一感兴趣区域(ROI),只需要创建包含边界信息的信息头:

Mat D(A,Rect(10,10,100,100));//使用矩形界定
Mat E=A(Range:all(),Range(1,3));//用行和列界定

如果矩阵属于多个Mat对象,那么当不再需要它时,最后一个使用它的对象,通过英勇计数机制来清理。我们无论什么时候复制一个Mat对象的信息头,都会增加矩阵的引用次数。反之,当一个头被释放之后,这个计数被减一;当计数值为0时,这个矩阵会被清理。但某些时候仍像复制矩阵本身(不只是信息头和矩阵指针),这时可以使用函数clone()或者copy To()。

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

现在改变F或G就不会影响Mat信息头所指向的矩阵。OpenCV函数中输出图像的内存分配是自动完成的(如果不是特别指定),使用OpenCV的C++接口时不需要考虑内存释放问题,赋值运算符和拷贝构造函数只复制信息头,使用函数clone()或者copyTo()来复制一幅图像的矩阵。下面给出用Mat()输出数据。

#include "opencv2/core/core.hpp"
#include "opencv2/highgui/highgui.hpp"
#include <iostream>
using namespace std;
using namespace cv;
//--------------------------------------【main( )函数】-----------------------------------------
//          描述:控制台应用程序的入口函数,我们的程序从这里开始执行
//-----------------------------------------------------------------------------------------------
int main(int,char**)
{
	//改变控制台的前景色和背景色
	system("color 8F"); 

	Mat I = Mat::eye(4, 4, CV_64F);
	I.at<double>(1,1) = CV_PI;
	cout << "\nI = " << I << ";\n" << endl;

	Mat r = Mat(10, 3, CV_8UC3);
	randu(r, Scalar::all(0), Scalar::all(255));

	cout << "r (OpenCV默认风格) = " << r << ";" << endl << endl;
	cout << "r (Python风格) = " << format(r,"python") << ";" << endl << endl;
	cout << "r (Numpy风格) = " << format(r,"numpy") << ";" << endl << endl;
	cout << "r (逗号分隔风格) = " << format(r,"csv") << ";" << endl<< endl;
	cout << "r (C语言风格) = " << format(r,"C") << ";" << endl << endl;

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

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

	vector<float> v;
	v.push_back(3);
	v.push_back(5);
	v.push_back(7);

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

	vector<Point2f> points(20);
	for (size_t i = 0; i < points.size(); ++i)
		points[i] = Point2f((float)(i * 5), (float)(i % 7));

	cout << "【二维点向量】points = " << points<<";";

	getchar();//按任意键退出

	return 0;


}

显示效果如下:

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值