OpenCV中Mat矩阵用法详解(包括多通道矩阵创建、矩阵运算等)

  在做项目期间,遇到过程序计算耗时长,实时性满足不了需求的问题。通过这一段时间的接触,总结了一些OpenCV中Mat类型的用法。


目录

一、 Mat类型的创建

1.常用的有两种创建方式:

2.多通道矩阵创建:

二、Mat类型赋值和访问

1.单通道矩阵访问:

2.多通道的矩阵访问:

三、矩阵运算

1 基本概念

2 矩阵加减法

3 矩阵乘法

4 矩阵转置

5 求逆矩阵

6 计算矩阵非零元素个数

7 均值和标准差

8 求最大最小值

四、矩阵变换

1.矩阵通道分离函数

2.矩阵合并


一、 Mat类型的创建

1.常用的有两种创建方式:

       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通道

2.多通道矩阵创建:

      需要改变的是数据类型,例如我要创建一个100行200列300通道的矩阵,并且存储的内容是double类型的。

       Mat img=cvCreatMat(100, 200, CV_8FC(300));   其中300可以根据通道数而改变。

二、Mat类型赋值和访问

1.单通道矩阵访问:

    例如对img矩阵中第一行第一列赋值(同样也适用于访问):

    img.at(0,0)=0.0;

2.多通道的矩阵访问:

    对矩阵第一个通道第一行第一列赋值(同样也适用于访问):

    img.at>(行,列)[通道]=0.0;

三、矩阵运算

基本概念

 

 OpenCV的Mat类允许所有的矩阵运算。

 

2 矩阵加减法

 

我们可以使用"+"和"-"符号进行矩阵加减运算。

  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;

         OpenCV中Mat矩阵用法详解(包括多通道矩阵创建、矩阵运算等)_第1张图片

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 = "<

meanStdDev(m3, mean3, stddev3);

cout<<"mean3 = "<

cout<<"stddev3 = "<

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 = "<

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();

 

四、矩阵变换

1.矩阵通道分离函数

 

split函数的功能是通道分离

原型

void split(const Mat& src,Mat *mvBegin)

 

void split(InputArray m, OutputArrayOfArrays mv);

用法很显然,第一个参数为要进行分离的图像矩阵,第二个参数可以是Mat数组的首地址,或者一个vector对象


std::vector 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 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);

  10. merge(aChannels, mergeImg);


 

 上述文字及代码是本人亲手敲上去的,不对的地方请指正,希望对各位有帮助,欢迎大家跟我交流。

    转载记得加上原链接,谢谢~

你可能感兴趣的:(OpenCV中Mat矩阵用法详解(包括多通道矩阵创建、矩阵运算等))