OpenCV中Mat矩阵⽤法详解(包括多通道矩阵创建、矩阵运
算等)
在做项⽬期间,遇到过程序计算耗时长,实时性满⾜不了需求的问题。通过这⼀段时间的接触,总结了⼀些OpenCV中Mat类型的⽤法。⽬录
⼀、 Mat类型的创建
1.常⽤的有两种创建⽅式:
1. Mat img(2, 4, CV_8UC3, Scalar(0, 255, 255));
2. Mat img=cvCreatMat(2, 4, CV_8UC3);  需要注意的是这种创建⽅式在⽤完的时候需要释放。lease();
其中:(2,4)表⽰创建的是2⾏4列的矩阵,CV_8UC3表⽰数据类型。
常⽤的数据类型:
CV_8UC1// 8位⽆符号单通道
CV_8UC3// 8位⽆符号3通道
CV_32FC1// 32位浮点型单通道
CV_32FC3// 32位浮点型3通道
2.多通道矩阵创建:
需要改变的是数据类型,例如我要创建⼀个100⾏200列300通道的矩阵,并且存储的内容是double类型的。
Mat img=cvCreatMat(100, 200, CV_8FC(300));  其中300可以根据通道数⽽改变。
⼆、Mat类型赋值和访问
1.单通道矩阵访问:
例如对img矩阵中第⼀⾏第⼀列赋值(同样也适⽤于访问):
img.at<double>(0,0)=0.0;
2.多通道的矩阵访问:
对矩阵第⼀个通道第⼀⾏第⼀列赋值(同样也适⽤于访问):
img.at<vec<;数据类型,总通道数>>(⾏,列)[通道]=0.0;
三、矩阵运算
1 基本概念
OpenCV的Mat类允许所有的矩阵运算。
2 矩阵加减法rectangle函数opencv
我们可以使⽤"+"和"-"符号进⾏矩阵加减运算。
1. cv::Mat a= Mat::eye(Size(3,2), CV_32F);
2. cv::Mat b= Mat::ones(Size(3,2), CV_32F);
3. cv::Mat c= a+b;
4. cv::Mat d= a-b;
3 矩阵乘法
使⽤"*"号计算矩阵与标量相乘,矩阵与矩阵相乘(必须满⾜矩阵相乘的⾏列数对应规则)
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            //表⽰矩阵相乘
4 矩阵转置
矩阵转置是将矩阵的⾏与列顺序对调(第i⾏转变为第i列)形成⼀个新的矩阵。OpenCV通过Mat类的t()函数实现。Mat m1= Mat::eye(2,3, CV_32F);
Mat m1t = m1.t();// 转置
5 求逆矩阵
逆矩阵在某些算法中经常出现,在OpenCV中通过Mat类的inv()⽅法实现
Mat meinv = me.inv();// 求逆
单位矩阵的逆就是其本⾝。
6 计算矩阵⾮零元素个数
计算物体的像素或⾯积常需要⽤到计算矩阵中的⾮零元素个数,OpenCV中使⽤countNonZero()函数实现。
int nonZerosNum = countNonZero(me); // ⾮零元素个数
7 均值和标准差
OpenCV提供了矩阵均值和标准差计算功能,可以使⽤meanStdDev(src,mean,stddev)函数实现。
参数
src – 输⼊矩阵或图像
mean – 均值,OutputArray
stddev – 标准差,OutputArray
// 均值⽅差
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 = "<<endl<<m3<<endl<<endl;
meanStdDev(m3, mean3, stddev3);
cout<<"mean3 = "<<mean3<<endl;
cout<<"stddev3 = "<<stddev3<<endl;
system("pause");
8 求最⼤最⼩值
求输⼊矩阵的全局最⼤最⼩值及其位置,可使⽤函数:
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());
参数:
src – 输⼊单通道矩阵(图像).
minVal – 指向最⼩值的指针, 如果未指定则使⽤NULL
maxVal – 指向最⼤值的指针, 如果未指定则使⽤NULL
minLoc – 指向最⼩值位置(2维情况)的指针, 如果未指定则使⽤NULL
maxLoc – 指向最⼤值位置(2维情况)的指针, 如果未指定则使⽤NULL
mask – 可选的蒙版,⽤于选择待处理⼦区域
// 求极值最⼤、最⼩值及其位置
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 = "<<minVal<<endl;
cout<<"max value = "<<maxVal<<endl;
cout<<"minPt = ("<<minPt.x<<","<<minPt.y<<")"<<endl;
cout<<"maxPt = ("<<maxPt.x<<","<<maxPt.y<<")"<<endl;
cout<<endl;
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();
四、矩阵变换
1.矩阵通道分离函数
split函数的功能是通道分离
原型
void split(const Mat& src,Mat *mvBegin)
void split(InputArray m, OutputArrayOfArrays mv);
⽤法很显然,第⼀个参数为要进⾏分离的图像矩阵,第⼆个参数可以是Mat数组的⾸地址,或者⼀个vector<Mat>对象
std::vector<Mat> channels;
1. Mat aChannels[3];
2. //src为要分离的Mat对象
3. split(src, aChannels); //利⽤数组分离
4. split(src, channels); //利⽤vector对象分离
5.
6. imshow("B",channels[0]);
7. imshow("G",channels[1]);
8. imshow("R",channels[2]);
注意:opencv中,RGB三个通道是反过来的
2.矩阵合并
该函数⽤来合并通道
原型
版本⼀
void merge(const Mat* mv, size_t count, OutputArray dst);
第⼀个参数是图像矩阵数组,第⼆个参数是需要合并矩阵的个数,第三个参数是输出
版本⼆
void merge(const vector& mv, OutputArray dst );
第⼀个参数是图像矩阵向量容器,第⼆个参数是输出,这种⽅法⽆需说明需要合并的矩阵个数,vector对象⾃带说明简单例⼦
std::vector<Mat> channels;
1. Mat aChannels[3];
2.
3. split(src, channels); //分离到数组
4. split(src, aChannels); //分离到vector对象
5.
6. //do something
7. //xxxx
8.
9. merge(channels, 3, mergeImg);
0. merge(aChannels, mergeImg);

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。