OpenCV的基本矩阵操作与示例

 

OpenCV中的矩阵操作非常重要,本文总结了矩阵的创建、初始化以及基本矩阵操作,给出了示例代码,主要内容包括:

 

  • 创建与初始化
  • 矩阵加减法
  • 矩阵乘法
  • 矩阵转置
  • 矩阵求逆
  • 矩阵非零元素个数
  • 矩阵均值与标准差
  • 矩阵全局极值及位置
  • 其他矩阵运算函数列表

 

1. 创建与初始化矩阵

 

1.1 数据类型

建立矩阵必须要指定矩阵存储的数据类型,图像处理中常用的几种数据类型如下:

  1. CV_8UC1// 8位无符号单通道  
  2. CV_8UC3// 8位无符号3通道  
  3. CV_8UC4  
  4. CV_32FC1// 32位浮点型单通道  
  5. CV_32FC3// 32位浮点型3通道  
  6. CV_32FC4  

包括数据位深度8位、32位,数据类型U:uchar、F:float型以及通道数C1:单通道、C3:三通道、C4:四通道。

 

1.2 基本方法

我们可以通过载入图像来创建Mat类型矩阵,当然也可以直接手动创建矩阵,基本方法是指定矩阵尺寸和数据类型:

 

1.    // 基本方法  
2.     cv::Mat a(cv::Size(5,5),CV_8UC1); // 单通道  
3.     cv::Mat b = cv::Mat(cv::Size(5,5),CV_8UC3); //3通道每个矩阵元素包含3个uchar值  
4.     cout<<"a  = "<<endl<<a<<endl<<endl;  
5.     cout<<"b  = "<<endl<<b<<endl<<endl;  
6.     system("pause");

运行结果:

opencv矩阵非0 opencv矩阵操作_最小值

3通道矩阵中,一个矩阵元素包含3个变量。

 

1.3 初始化方法

上述方法不初始化矩阵数据,因此将出现随机值。如果想避免这种情况,可使用Mat类的几种初始化创建矩阵的方法:

1. // 初始化方法  
2.     cv::Mat mz = cv::Mat::zeros(cv::Size(5,5),CV_8UC1); // 全零矩阵  
3.     cv::Mat mo = cv::Mat::ones(cv::Size(5,5),CV_8UC1);  // 全1矩阵  
4.     cv::Mat me = cv::Mat::eye(cv::Size(5,5),CV_32FC1);  // 对角线为1的对角矩阵  
5.     cout<<"mz = "<<endl<<mz<<endl<<endl;  
6.     cout<<"mo = "<<endl<<mo<<endl<<endl;  
7.     cout<<"me = "<<endl<<me<<endl<<endl;

运行结果:

opencv矩阵非0 opencv矩阵操作_OpenCV_02

 

 

2. 矩阵运算

 

2.1 基本概念

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

 

2.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矩阵非0 opencv矩阵操作_OpenCV_03

 

 

 

2.3 矩阵乘法

使用"*"号计算矩阵与标量相乘,矩阵与矩阵相乘(必须满足矩阵相乘的行列数对应规则)

1. Mat m1= Mat::eye(2,3, CV_32F); //使用cv命名空间可省略cv::前缀,下同  
2. Mat m2= Mat::ones(3,2, CV_32F);  
3. cout<<"m1  = "<<endl<<m1<<endl<<endl;  
4. cout<<"m2  = "<<endl<<m2<<endl<<endl;  
5. // Scalar by matrix  
6. cout << "\nm1.*2 = \n" << m1*2 << endl;  
7. // matrix per element multiplication  
8. cout << "\n(m1+2).*(m1+3) = \n" << (m1+1).mul(m1+3) << endl;  
9. // Matrix multiplication  
10. cout << "\nm1*m2 = \n" << m1*m2 << endl;

 

opencv矩阵非0 opencv矩阵操作_OpenCV_04

 

2.4 矩阵转置

矩阵转置是将矩阵的行与列顺序对调(第i行转变为第i列)形成一个新的矩阵。OpenCV通过Mat类的t()函数实现。
 

1. // 转置  
2.     Mat m1= Mat::eye(2,3, CV_32F);    
3.     Mat m1t = m1.t();  
4.     cout<<"m1  = "<<endl<<m1<<endl<<endl;  
5.     cout<<"m1t  = "<<endl<<m1t<<endl<<endl;  
6.     system("pause");

运行结果:

 

opencv矩阵非0 opencv矩阵操作_opencv矩阵非0_05

 

 

2.5 求逆矩阵

逆矩阵在某些算法中经常出现,在OpenCV中通过Mat类的inv()方法实现
 

1. // 求逆  
2.     Mat meinv = me.inv();  
3.     cout<<"me  = "<<endl<<me<<endl<<endl;  
4.     cout<<"meinv = "<<endl<<meinv<<endl<<endl;  
5.     system("pause");

运行结果:

opencv矩阵非0 opencv矩阵操作_opencv矩阵非0_06

 

单位矩阵的逆就是其本身。
 

 

2.6 计算矩阵非零元素个数

计算物体的像素或面积常需要用到计算矩阵中的非零元素个数,OpenCV中使用countNonZero()函数实现。

  1. // 非零元素个数  
  2.     int nonZerosNum = countNonZero(me); // me为输入矩阵或图像  
  3.     cout<<"me  = "<<endl<<me<<endl;  
  4.     cout<<"me中非零元素个数 = "<<nonZerosNum<<endl<<endl;  
  5.     system("pause");  

运行结果:

opencv矩阵非0 opencv矩阵操作_标准差_07

 

2.7 均值和标准差

OpenCV提供了矩阵均值和标准差计算功能,可以使用meanStdDev(src,mean,stddev)函数实现。

 

参数

    • src – 输入矩阵或图像
    • mean – 均值,OutputArray
    • stddev – 标准差,OutputArray
    1. // 均值方差  
    2.     Mat mean;  
    3.     Mat stddev;  
    4.     meanStdDev(me, mean, stddev); //me为前文定义的5×5对角阵  
    5.     cout<<"mean = "<<mean<<endl;  
    6.     cout<<"stddev = "<<stddev<<endl;  
    7.     system("pause");

    运行结果:

    opencv矩阵非0 opencv矩阵操作_opencv矩阵非0_08

    需要说明的是,如果src是多通道图像或多维矩阵,则函数分别计算不同通道的均值与标准差,因此返回值mean和stddev为对应维度的向量。

    1. Mat mean3;  
    2. Mat stddev3;  
    3. Mat m3(cv::Size(5,5),CV_8UC3,Scalar(255,200,100));  
    4. cout<<"m3  = "<<endl<<m3<<endl<<endl;  
    5. meanStdDev(m3, mean3, stddev3);  
    6. cout<<"mean3 = "<<mean3<<endl;  
    7. cout<<"stddev3 = "<<stddev3<<endl;  
    8. system("pause");

    多通道矩阵运算结果:

    opencv矩阵非0 opencv矩阵操作_OpenCV_09

     

    opencv矩阵非0 opencv矩阵操作_最小值_10

     

    2.8 求最大最小值

    求输入矩阵的全局最大最小值及其位置,可使用函数:

    1. void minMaxLoc(InputArray src, CV_OUT double* minVal,  
    2.                            CV_OUT double* maxVal=0, CV_OUT Point* minLoc=0,  
    3.                            CV_OUT Point* maxLoc=0, InputArray mask=noArray());  
     
    参数:
    • src – 输入单通道矩阵(图像).
    • minVal – 指向最小值的指针, 如果未指定则使用NULL
    • maxVal – 指向最大值的指针, 如果未指定则使用NULL
    • minLoc – 指向最小值位置(2维情况)的指针, 如果未指定则使用NULL
    • maxLoc – 指向最大值位置(2维情况)的指针, 如果未指定则使用NULL
    • mask – 可选的蒙版,用于选择待处理子区域
     
     
    1. // 求极值 最大、最小值及其位置  
    2.     Mat img = imread("Lena.jpg",0);  
    3.     imshow("original image",img);  
    4.   
    5.     double minVal=0,maxVal=0;  
    6.     cv::Point minPt, maxPt;  
    7.     minMaxLoc(img,&minVal,&maxVal,&minPt,&maxPt);  
    8.     cout<<"min value  = "<<minVal<<endl;  
    9.     cout<<"max value  = "<<maxVal<<endl;  
    10.     cout<<"minPt = ("<<minPt.x<<","<<minPt.y<<")"<<endl;  
    11.     cout<<"maxPt = ("<<maxPt.x<<","<<maxPt.y<<")"<<endl;  
    12.     cout<<endl;  
    13.   
    14.     cv::Rect rectMin(minPt.x-10,minPt.y-10,20,20);  
    15.     cv::Rect rectMax(maxPt.x-10,maxPt.y-10,20,20);  
    16.   
    17.     cv::rectangle(img,rectMin,cv::Scalar(200),2);  
    18.     cv::rectangle(img,rectMax,cv::Scalar(255),2);  
    19.   
    20.     imshow("image with min max location",img);  
    21.     cv::waitKey();

    运行结果:

    opencv矩阵非0 opencv矩阵操作_标准差_11

     

    opencv矩阵非0 opencv矩阵操作_最小值_12

    输入图像及其最大最小值位置

     

     

    3. 其他矩阵运算

    其他矩阵运算函数见下表:

     

     

    Function (函数名)

    Use (函数用处)

    add

    矩阵加法,A+B的更高级形式,支持mask

    scaleAdd

    矩阵加法,一个带有缩放因子dst(I) = scale * src1(I) + src2(I)

    addWeighted

    矩阵加法,两个带有缩放因子dst(I) = saturate(src1(I) * alpha + src2(I) * beta + gamma)

    subtract

    矩阵减法,A-B的更高级形式,支持mask

    multiply

    矩阵逐元素乘法,同Mat::mul()函数,与A*B区别,支持mask

    gemm

    一个广义的矩阵乘法操作

    divide

    矩阵逐元素除法,与A/B区别,支持mask

    abs

    对每个元素求绝对值

    absdiff

    两个矩阵的差的绝对值

    exp

    求每个矩阵元素 src(I) 的自然数 e 的 src(I) 次幂 dst[I] = esrc(I)

    pow

    求每个矩阵元素 src(I) 的 p 次幂 dst[I] = src(I)p

    log

    求每个矩阵元素的自然数底 dst[I] = log|src(I)| (if src != 0)

    sqrt

    求每个矩阵元素的平方根

    min, max

    求每个元素的最小值或最大值返回这个矩阵 dst(I) = min(src1(I), src2(I)), max同

    minMaxLoc

    定位矩阵中最小值、最大值的位置

    compare

    返回逐个元素比较结果的矩阵

    bitwise_and, bitwise_not, bitwise_or, bitwise_xor

    每个元素进行位运算,分别是和、非、或、异或

    cvarrToMat

    旧版数据CvMat,IplImage,CvMatND转换到新版数据Mat

    extractImageCOI

    从旧版数据中提取指定的通道矩阵给新版数据Mat

    randu

    以Uniform分布产生随机数填充矩阵,同 RNG::fill(mat, RNG::UNIFORM)

    randn

    以Normal分布产生随机数填充矩阵,同 RNG::fill(mat, RNG::NORMAL)

    randShuffle

    随机打乱一个一维向量的元素顺序

    theRNG()

    返回一个默认构造的RNG类的对象

     theRNG()::fill(...)

    reduce

    矩阵缩成向量

    repeat

    矩阵拷贝的时候指定按x/y方向重复

    split

    多通道矩阵分解成多个单通道矩阵

    merge

    多个单通道矩阵合成一个多通道矩阵

    mixChannels

    矩阵间通道拷贝,如Rgba[]到Rgb[]和Alpha[]

    sort, sortIdx

    为矩阵的每行或每列元素排序

    setIdentity

    设置单元矩阵

    completeSymm

    矩阵上下三角拷贝

    inRange

    检查元素的取值范围是否在另两个矩阵的元素取值之间,返回验证矩阵

    checkRange

    检查矩阵的每个元素的取值是否在最小值与最大值之间,返回验证结果bool

    sum

    求矩阵的元素和

    mean

    求均值

    meanStdDev

    均值和标准差

    countNonZero

    统计非零值个数

    cartToPolar, polarToCart

    笛卡尔坐标与极坐标之间的转换

    flip

    矩阵翻转

    transpose

    矩阵转置,比较 Mat::t() AT

    trace

    矩阵的迹

    determinant

    行列式 |A|, det(A)

    eigen

    矩阵的特征值和特征向量

    invert

    矩阵的逆或者伪逆,比较 Mat::inv()

    magnitude

    向量长度计算 dst(I) = sqrt(x(I)2 + y(I)2)

    Mahalanobis

    Mahalanobis距离计算

    phase

    相位计算,即两个向量之间的夹角

    norm

    求范数,1-范数、2-范数、无穷范数

    normalize

    标准化

    mulTransposed

    矩阵和它自己的转置相乘 AT * A, dst = scale(src - delta)T(src - delta)

    convertScaleAbs

    先缩放元素再取绝对值,最后转换格式为8bit型

    calcCovarMatrix

    计算协方差阵

    solve

    求解1个或多个线性系统或者求解最小平方问题(least-squares problem)

    solveCubic

    求解三次方程的根

    solvePoly

    求解多项式的实根和重根

    dct, idct

    正、逆离散余弦变换,idct同dct(src, dst, flags | DCT_INVERSE)

    dft, idft

    正、逆离散傅立叶变换, idft同dft(src, dst, flags | DTF_INVERSE)

    LUT

    查表变换

    getOptimalDFTSize

    返回一个优化过的DFT大小

    mulSpecturms

    两个傅立叶频谱间逐元素的乘法