OpenCV Mat类基本操作

OpenCv2.X采用全新的图像数据结构Mat代替C接口cvMat和IplImage。全新Mat类不需要我们手动为其开辟空间,也不需要立即释放内存空间,它能够自动管理内存。Mat类由矩阵头和指向存储所有像素值的矩阵的指针构成。Mat类表示一个n维的密集数值单通道或多通道数组,它可用于存储实数或复数值的向量和矩阵、灰度或彩色图像等。

Mat类

class CV_EXPORTS Mat
{
public:
	
	int flags; //标志位
	int dims; //数组的维数
	int rows, cols; //行和列的数量
	uchar* data; //指向数据的指针
	int* refcount; //指针的引用计数器,当阵列指向用户分配的数据时,指针为NULL
};

 Mat类常用的构造方法

  • 无参数构造方法
Mat::Mat()
  • 指定类型的二维数组,创建行数为rows,列数为cols,类型为type的图像
Mat::Mat(int rows,int cols,int type);
  • 创建大小为size,类型为type的图像
Mat::Mat(Size size,int type)
  • 指定类型的二维数组,并指定初始化值。创建行数为rows,列数为cols,类型为type的图像,并将所有元素初始化为值s
Mat::Mat(int rows,int cols,int type,const Scalar&s);
  • m和新对象共用图像数据,将m赋值给新创建的对象,此操作不会对图像数据进行复制,m和新对象共用图像数据。
Mat::Mat(const Mat& m)

对上面的几种构造函数应用举例

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
	Mat img1; //创建无初始化矩阵
	Mat img2(6, 6, CV_8UC1); //创建6行6列类型为8位单通道矩阵
	Mat img3(Size(7, 7), CV_8UC3); //创建大小为7*7类型为8位3通道矩阵
	Mat img4(8, 8, CV_32FC2, Scalar(1, 3)); //创建一个用1+3j填充的8*8复矩阵
	Mat img5(Size(9, 9), CV_8UC3, Scalar(1, 2, 3));//创建大小为9*9类型的8位3通道矩阵
	Mat img6(img2);//将img2的值赋给img6,共用数据图像
	cout << "img1: " << endl << img1 << endl << endl;
	cout << "img2: " << endl << img2 << endl << endl;
	cout << "img3: " << endl << img3 << endl << endl;
	cout << "img4: " << endl << img4 << endl << endl;
	cout << "img5: " << endl << img5 << endl << endl;
	cout << "img6: " << endl << img6 << endl << endl;
}

运行结果如下: 

 

上面列举了Mat的基本构造函数,主要分为几个类型:要求输入行数和列数来构造一个二维数组的、使用cv::Size对象来构造一个二维数组的、 

 Mat基本操作

Mat类常用函数功能
Mat::row创建一个具有指定了矩阵头中行数的参数的矩阵                
Mat::col创建一个具有指定了矩阵头中列数的参数的矩阵
Mat::rowRange为指定的行创建一个新的矩阵头,可取指定区间行元素
Mat::colRange为指定的列创建一个矩阵头,可取指定列区间元素
Mat::clone创建一个数组及其基础数据的完整副本
Mat::copyTo把矩阵复制到另一个矩阵中
Mat::convertTo在放缩或不放缩的情况下转换为另一种数据类型
Mat::zeros返回指定的大小和类型的零数组
Mat::ones返回一个指定的大小和类型全为1的数组
Mat::channels返回矩阵通道的数目
Mat::empty返回数组有没有元素,没有则返回true
Mat::at返回对指定元素数组的引用

对上述函数应用举例:

#include<opencv2/imgproc/imgproc.hpp>
#include<opencv2/highgui/highgui.hpp>
#include<iostream>
using namespace std;
using namespace cv;
int main()
{
	Mat img1(10, 8, CV_8UC1, Scalar(5));
	//获取矩阵行列数
	cout << "img1 row: " << img1.rows << endl; //10
	cout << "img1 col: " << img1.cols << endl; //8

	//获取指定行列元素
	cout << img1.rowRange(1, 3) << endl;
	cout << img1.colRange(2, 4) << endl; //区间范围是包括左边界,不包括右边界

	//创建8*8复数矩阵1+5j
	Mat img2(8, 8, CV_32FC2, Scalar(1, 5));
	//利用create方法重新创建10*10的8位无符号3通道矩阵
	img2.create(10, 10, CV_8UC3);
	cout << "img2 channels: " << img2.channels() << endl;//3

	//转换矩阵类型
	img2.convertTo(img2, CV_32F);
	cout << "img2 depth: " << img2.depth() << endl;//5
	//depth是预定义值	
		//#define CV_8U   0
		//#define CV_8S   1
		//#define CV_16U  2
		//#define CV_16S  3
		//#define CV_32S  4
		//#define CV_32F  5
		//#define CV_64F  6

	//zeros创建矩阵
	Mat img3 = Mat::zeros(img2.rows, img2.cols, CV_8UC1);
	cout << "img3" << endl << img3 << endl;

}

运行结果如下: 

 

为了方便查看每个函数的作用,下面将每一步的结果单独显示出来。

将img1的第4行元素变换成img1的第5行元素乘2

img1.row(4) = img1.row(5) * 2;
	cout << img1 << endl;

 

将img4矩阵赋值为img1的第4列

Mat img4 = img1.col(4);
	cout << img4 << endl;

 

 

 将img1矩阵的第1列复制到img4中

img1.col(1).copyTo(img4);
	cout << img4<<endl;

 

 

独立获取数组元素

访问一个元素的两种主要方法是通过位置或者迭代器访问

直接访问是通过模板函数at<>()来实现的。这个函数的工作方式是先将at<>()特化到矩阵所包含的数据类型,然后使用你所想要的数据的行和列的位置访问该元素。

举一个简单的例子:

cv::Mat m = cv::Mat::eye(10,10,32FC1);
cout<<''Element(3,3) is << m.at<float>(3,3);

多通道数组的操作与单通道数组类似:

cv::Mat m = cv::Mat::eye(10,10,32FC2);
cout<<"Element(3,3) is "<<m.at<cv::Vec2f>(3,3)[0]<<m.at<cv::Vec2f>(3,3)[1];

at<>()访问器函数的变体 

M.at<int>(i);                //整型数组M中的元素i
M.at<float>(i,j);            //浮点型数组M中的元素(i,j)
M.at<int>(pt);               //整型矩阵M中处于(pt.x,pt.y)的元素
M.at<float>(i,j,k);          //三维浮点型矩阵M中处于(i,j,k)位置的元素
M.at<uchar>(idx);            //无符号字符数组M中位于idx[]所索引的n维位置的元素

通过块访问数组元素

Mat区块访问

m.row(i);                                //m中第i行数组
m.col(j);                                //m中第j列数组
m.rowRange(i0,i1);                       //m中第i0行到i1-1行所构成的数组
m.rowRange(cv::Range(i0,i1));            //m中第i0行到i1-1行所构成的数组
m.colRange(j0,j1);                       //m中第j0列到j1-1列所构成的数组
m.colRange(cv::Range(j0,j1));            //m中第j0列到j1-1列所构成的数组
m.diag(d);                               //m中偏移为d的对角线所组成的数组
m(cv::Range(i0,i1),cv::Range(j0,j1));    //m中从点(i0,j0)到(i1-1,j1-1)所包含数据组成的数组
m(cv::Rect(i0,j0,w,h));                //m中从点(i0,j0)到(i0+w-1,j0+h-1)所包含数据组成的数组

Mat的更多函数成员

m1=m0.clone();           //从m0进行完全复制,将复制所有的数据元素
m0.copyTo(m1);           //将m0复制给m1,如果有必要,将给m1重分配内存空间(等同于m1=m0.clone())
m0.copyTo(m1,mask);      //和m0.copyTo(m1)一样,但是只复制mask所指示的区域
m0.convertTo(m1,type,scale,offset);
                   //转换m0中元素的类型并且在尺度变换(默认为1)和增加偏置(默认为0)之后赋值给m1
m0.assignTo(m1,type);    //也是将m0赋值给m1;
m0.setTo(s,mask);        //设置m0所有元素为s,如果存在mask,则只对mask区域操作
m0.reshape(chan,rows);   //改变二维数组的有效形状,chan和rows为0表示不做更改
m0.adjustROI(t,b,l,r);   //通过四个值t(上),b(下),l(左),r(右)调整ROI范围
m0.locateROI(size,offset);   
      //将m0的全尺寸写入变量size,如果m0只是一个大矩阵的一小块区域,还会写入一个Point类型的offset
m0.type();               //返回m0元素的类型
m0.depth();              //返回m0通道中的元素类型
m0.channels();           //返回m0的通道数目
m0.size();               //以Size返回m0的大小
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值