在做项目期间,遇到过程序计算耗时长,实时性满足不了需求的问题。通过这一段时间的接触,总结了一些OpenCV中Mat类型的用法。
目录
一、 Mat类型的创建
1.常用的有两种创建方式:
2.多通道矩阵创建:
二、Mat类型赋值和访问
1.单通道矩阵访问:
2.多通道的矩阵访问:
三、矩阵运算
1 基本概念
2 矩阵加减法
3 矩阵乘法
4 矩阵转置
5 求逆矩阵
6 计算矩阵非零元素个数
7 均值和标准差
8 求最大最小值
四、矩阵变换
1.矩阵通道分离函数
2.矩阵合并
1. Mat img(2, 4, CV_8UC3, Scalar(0, 255, 255));
2. Mat img=cvCreatMat(2, 4, CV_8UC3); 需要注意的是这种创建方式在用完的时候需要释放。img.release();
其中:(2,4)表示创建的是2行4列的矩阵,CV_8UC3表示数据类型。
常用的数据类型:
CV_8UC1// 8位无符号单通道
CV_8UC3// 8位无符号3通道
CV_32FC1// 32位浮点型单通道
CV_32FC3// 32位浮点型3通道
需要改变的是数据类型,例如我要创建一个100行200列300通道的矩阵,并且存储的内容是double类型的。
Mat img=cvCreatMat(100, 200, CV_8FC(300)); 其中300可以根据通道数而改变。
例如对img矩阵中第一行第一列赋值(同样也适用于访问):
img.at
对矩阵第一个通道第一行第一列赋值(同样也适用于访问):
img.at
OpenCV的Mat类允许所有的矩阵运算。
我们可以使用"+"和"-"符号进行矩阵加减运算。
cv::Mat a= Mat::eye(Size(3,2), CV_32F);
cv::Mat b= Mat::ones(Size(3,2), CV_32F);
cv::Mat c= a+b;
cv::Mat d= a-b;
使用"*"号计算矩阵与标量相乘,矩阵与矩阵相乘(必须满足矩阵相乘的行列数对应规则)
Mat m1= Mat::eye(2,3, CV_32F); //使用cv命名空间可省略cv::前缀,下同
Mat m2= Mat::ones(3,2, CV_32F);
(m1+1).mul(m1+3) //表示矩阵元素相乘(点乘)
m1*m2 //表示矩阵相乘
矩阵转置是将矩阵的行与列顺序对调(第i行转变为第i列)形成一个新的矩阵。OpenCV通过Mat类的t()函数实现。
Mat m1= Mat::eye(2,3, CV_32F);
Mat m1t = m1.t();// 转置
逆矩阵在某些算法中经常出现,在OpenCV中通过Mat类的inv()方法实现
Mat meinv = me.inv();// 求逆
单位矩阵的逆就是其本身。
计算物体的像素或面积常需要用到计算矩阵中的非零元素个数,OpenCV中使用countNonZero()函数实现。
int nonZerosNum = countNonZero(me); // 非零元素个数
OpenCV提供了矩阵均值和标准差计算功能,可以使用meanStdDev(src,mean,stddev)函数实现。
参数
// 均值方差
Mat mean;
Mat stddev;
meanStdDev(me, mean, stddev); //me为前文定义的5×5对角阵
需要说明的是,如果src是多通道图像或多维矩阵,则函数分别计算不同通道的均值与标准差,因此返回值mean和stddev为对应维度的向量。
Mat mean3;
Mat stddev3;
Mat m3(cv::Size(5,5),CV_8UC3,Scalar(255,200,100));
cout<<"m3 = "<
meanStdDev(m3, mean3, stddev3);
cout<<"mean3 = "<
cout<<"stddev3 = "<
system("pause");
求输入矩阵的全局最大最小值及其位置,可使用函数:
void minMaxLoc(InputArray src, CV_OUT double* minVal,
CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,
CV_OUT Point* maxLoc=0, InputArray mask=noArray());
参数:
// 求极值 最大、最小值及其位置
Mat img = imread("Lena.jpg",0);
imshow("original image",img);
double minVal=0,maxVal=0;
cv::Point minPt, maxPt;
minMaxLoc(img,&minVal,&maxVal,&minPt,&maxPt);
cout<<"min value = "<
cout<<"max value = "<
cout<<"minPt = ("<
cout<<"maxPt = ("<
cout<
cv::Rect rectMin(minPt.x-10,minPt.y-10,20,20);
cv::Rect rectMax(maxPt.x-10,maxPt.y-10,20,20);
cv::rectangle(img,rectMin,cv::Scalar(200),2);
cv::rectangle(img,rectMax,cv::Scalar(255),2);
imshow("image with min max location",img);
cv::waitKey();
split函数的功能是通道分离
原型
void split(const Mat& src,Mat *mvBegin)
void split(InputArray m, OutputArrayOfArrays mv);
用法很显然,第一个参数为要进行分离的图像矩阵,第二个参数可以是Mat数组的首地址,或者一个vector
std::vector
Mat aChannels[3];
//src为要分离的Mat对象
split(src, aChannels); //利用数组分离
split(src, channels); //利用vector对象分离
imshow("B",channels[0]);
imshow("G",channels[1]);
imshow("R",channels[2]);
注意:opencv中,RGB三个通道是反过来的
该函数用来合并通道
原型
版本一
void merge(const Mat* mv, size_t count, OutputArray dst);
第一个参数是图像矩阵数组,第二个参数是需要合并矩阵的个数,第三个参数是输出
版本二
void merge(const vector& mv, OutputArray dst );
第一个参数是图像矩阵向量容器,第二个参数是输出,这种方法无需说明需要合并的矩阵个数,vector对象自带说明
简单例子
std::vector
Mat aChannels[3];
split(src, channels); //分离到数组
split(src, aChannels); //分离到vector对象
//do something
//xxxx
merge(channels, 3, mergeImg);
merge(aChannels, mergeImg);
上述文字及代码是本人亲手敲上去的,不对的地方请指正,希望对各位有帮助,欢迎大家跟我交流。
转载记得加上原链接,谢谢~