opencv学习——图像和大型数组类型

cv::Mat类

表示任意维度的稠密数组,其数据可以看做是按照栅格扫描顺序存储的n维数组

所有的矩阵都包含

(1)表示数组类型的元素flag

(2)表示维度的元素dims——分别表示行和列的数目的元素rows和cols(dims>2时无效)

(3)表示数据真正存储位置的data指针

(4)表示该内存区域有多少个引用的refcount元素

cv::Mat m;
三行十列,数据类型是三通道的32位浮点数据
m.create(3, 10, CV_32FC3);
第一个通道设置成1.0, 第二个通道0.0,第三个通道1.0
m.setTo(cv::Scalar(1.0f, 0.0f, 1.0f));

等效于
cv::Mat m(3, 10, CV_32FC3, cv::Scalar(1.0f, 0.0f, 1.0f));

数据类型 CV_{8U, 16S, 16U, 32S, 32F, 64F }C{1, 2, 3}

cv::Mat的构造函数

cv::Mat::Mat()

默认构造函数,生成一个矩阵并由OpenCV提供的函数(一般是Mat::create() 和 cv::imread() )来分配储存空间。

Mat类可以分为两个部分:矩阵头 和 指向像素数据的矩阵指针

矩阵头 包括数字图像的矩阵尺寸、存储方法、存储地址和引用次数等,矩阵头的大小是一个常数,不会随着图像的大小而改变,但是保存图像像素数据的矩阵则会随着图像的大小而改变,通常数据量会很大,比矩阵头大几个数量级。这样,在图像复制和传递过程中,主要的开销是由存放图像像素的矩阵而引起的。因此,OpenCV使用了引用次数,当进行图像复制和传递时,不再复制整个Mat数据,而只是复制矩阵头和指向像素矩阵的指针,例如:

cv::Mat a ; //默认构造函数,创建矩阵头
a = cv::imread("test.jpg");//读入图像,矩阵指针指向该像素数据
cv::Mat b = a ;//复制 

上面的a,b有各自的矩阵头,但是其矩阵指针指向同一个矩阵,也就是其中任何一个改变了矩阵数据都会影响另外一个
那么,多个Mat共用一个矩阵数据,最后谁来释放矩阵数据呢?
这就是引用计数的作用,当Mat对象每被复制一次时,就会将引用计数加1,而每销毁一个Mat对象(共用同一个矩阵数据)时引用计数会被减1,当引用计数为0时,矩阵数据会被清理。

常用构造函数

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

在创建对象同时,提供矩阵的大小(rows,行数;cols ,列数),以及存储类型(type)

cv::Mat::Mat(Size size,int type )   

Size类等效于一个成对数据,size::Size(cols,rows),特别注意 cols和rows的位置

cv::Mat::Mat(int ndims,const int *  sizes,int type,const Scalar& s) 

该构造函数与使用了Scalar参数,作用是能够通过Scalar数据类来初始化元素值,例如,我们要生成一张白色背景的图片:

Mat src1(300, 400, CV_8UC3,Scalar(255,255,255));
imshow("test", src1);
cv::Mat::Mat(const Mat & m)

引用m矩阵,注意,这里是引用值

 

构造cv::Mat的静态方法

cv::Mat::zeros(rows, cols, type); 构造一个值全为0的矩阵
cv::Mat::ones(rows, cols, type); 构造一个值全为1的矩阵
cv::Mat::eye(rows, cols, type); 构造一个单位矩阵

访问矩阵的方法

直接访问 模板函数at<>()

at函数的功能是访问矩阵元素,根据不同的使用场景,有多个重载函数可供选择。
如,访问一个二维的矩阵,可用at函数原型为:

Mat src = imread("test.jpg");
int elem = src.at<int>(0,0);

访问test.jpg图像的(0 , 0)元素

channels函数

int cv::Mat::channels   ()  const

返回图像的通道数

clone函数

矩阵复制

这个函数很常用,试比较

Mat image1 = imread("test.png",IMREAD_COLOR);
Mat image2 = image1;

此时,image2得到的是image1的一个引用,是一种基于浅拷贝策略的赋值,即image2实际上指向的是image1的内存单元。当image1提前被释放掉的时候,image2访问无效。

如果想要 复制 image1的数据内容,而不仅仅是 指向,那么就需要用clone 函数 ,该函数实现的是“深拷贝”,能够把Mat的数据单元复制给其他对象,比如:

Mat image1 = imread("test.png",IMREAD_COLOR);
Mat image2 = image1.clone();

此时image2不再受限于image1的状态,可以自由操作。
实际上,OpenCV 对于Mat的的= 的赋值构造函数并没有做太多的修改,我们通过该赋值构造函数得到的只是一个引用。

 

 

 


---------------------  
作者:CodeLike  
来源:CSDN  
原文:https://blog.csdn.net/CV_Jason/article/details/54928920  
版权声明:本文为博主原创文章,转载请附上博文链接!

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值