1. Mat矩阵操作
1.1 创建矩阵
//第一个参数是rows,第二个参数是cols
Mat image(240, 320, CV_8UC3);
//不能为矩阵设置初值,在改变尺寸是重新分配image矩阵
image.create(480, 640, CV_8UC3);
//定义并初始化一个3×3的32bit浮点数矩阵,每个元素都设为5
Mat A(3, 3, CV_32F, Scalar(5));
Mat B(3, 3, CV_32F);
B = Scalar(5);
Mat C = Mat::ones(3, 3, CV_32F) * 5;
Mat D = Mat::zeros(3, 3, CV_32F) + 5;
//使用数组初始化矩阵
/***用Bdata数组里的值初始化,然后克隆一下赋给E矩阵。之所以克隆,是因为用一个数组去初始化一个矩阵,这个矩阵引用了数组的内存地址。不克隆的话,上面例程的后果是Bdata数组、Mat(2,2…)这个临时变量矩阵、E矩阵都指向统一内存空间。***/
double a = CV_PI / 3;
float Bdata[] = { cos(a), -sin(a), sin(a), cos(a) };
Mat E = Mat(2, 2, CV_32F, Bdata).clone();
//对小矩阵使用逗号分隔符初始化函数
Mat F = (Mat_<double>(3, 3) << 1, 2, 3, 4, 5, 6, 7, 8, 9);
//符合正太分布的随机数矩阵,第二个参数是随机数下限,包含该数;第三个参数是随机数上限,不包含该数。
randu(image, Scalar(0), Scalar(256));
//高斯分布的随机数矩阵;第二个参数是均值,第三个参数是标差。
randn(image, Scalar(128), Scalar(10));
1.2 赋值运算
/***赋值运算符和复制构造函数 (构造函数)只复制头,没有数据***/
Mat A,C; //仅创建了头部
Mat B(A); //复制构造函数
C=A; //复制运算
src.copyTo(dst); //把src矩阵中的数据拷贝到dst
src.convertTo(dst, type, scale, shift);//缩放并转换,type负值(常用-1)则输出矩阵和输入矩阵类型相同
//创建一个矩阵头,指向m矩阵的对角线,i=0时表示主对角线,i>0表示下半边的对角线,i<0表示上半边的对角线。
m.diag(i);
//翻转矩阵,dir是翻转方向,0表示沿x轴翻转,1表示沿y轴翻转,-1表示沿x轴和y轴都进行翻转。
flip(src,dst,dir);
1.3 算术运算
//1.加法
I = I1 + I2; //等同add(I1,I2,I);
add(I1, I2, dst, mask, dtype);
scaleAdd(I1, scale, I2, dst); //dst=scale*I1+I2;
//2.减法
absdiff(I1, I2, I); //I=|I1-I2|;
A - B; A - s; s - A; -A;
subtract(I1, I2, dst);
//3.乘法
//mul:两个Mat矩阵对应位的乘积,计算结果是跟A或B行列数一致的一个Mat矩阵
//若声明AB时没有定义AB的数据类型,则默认AB的数据类型跟A和B保存一致;
I = I.mul(I); //点乘,I.mul(I,3);-->I=3*I.^2
Mat C = A.mul(5 / B); //==divide(A,B,C,5);
multiply();
mulTransposed()//计算矩阵和矩阵的转置的乘积,AT * A
// A*B要求矩阵类型是CV_32F、 CV_64FC1、 CV_32FC2、 CV_64FC2 。若选用其他类型,比如CV_8UC1,编译器会报错:
A * B; //矩阵相乘
A.dot(B); //A和B点乘,然后求所有元素和,向量积
pow(src, double p, dst); //求幂,如果p是整数dst(I)=src(I)^p;其他|src(I)|^p
sqrt()//计算矩阵逐元素的平方根
Mat::cross(Mat); //三维向量(或矩阵)的叉乘,A.cross(B)
//4.除法
divide(I1, I2, dst, scale, int dtype = -1); //dst=saturate_cast(I1*scale/I2);
A / B; alpha / A; //都是点除
//5.转置
A.t()
transpose()
//6.求逆
//Type: CV_LU - 最佳主元选取的高斯消除法
//CV_SVD - 奇异值分解法 (SVD)
//CV_SVD_SYM - 对正定对称矩阵的 SVD 方法
A.inv(type)
invert(temp, temp1, DECOMP_SVD);
//7.解方程
/***Flag可以为空即:SVD::compute(A,D,U,V),D为列矩阵,元素为A的特征值,
A=U*diag(D)*V ,diag(D)是把D变成对角阵,与matlab相比,U与matlab值相同,正负号不同,
V为matlab中V的转置,正负号不同。***/
SVD::compute(A,D,U,V,flag=0);
solve()//求出线性方程组的解
solveCubic()//找到三次方程的实根
solvePoly()//找到多项式方程的复根
//8.最大最小值,均值
mean()//求均值
//均值和标准差,src为多通道或多维矩阵时,则函数分别计算不同通道的均值与标准差,
//因此返回的mean和stddev为对应维度的向量;
meanStdDev(src,mean,stddev)
[minMaxLoc() vs minMaxIdx()](https://blog.csdn.net/fangyan90617/article/details/100540020)
//9.矩阵行列求和
/**dim :0一行,1一列,-1时维数将根据输出向量的大小自动选择.
rtype :
简化操作的方式,FLAG:
CV_REDUCE_SUM-输出是矩阵的所有行/列的和.
CV_REDUCE_AVG-输出是矩阵的所有行/列的平均向量.
CV_REDUCE_MAX-输出是矩阵的所有行/列的最大值.
CV_REDUCE_MIN-输出是矩阵的所有行/列的最小值.**/
reduce( inputArry src, outputArry, int dim, int rtype,int dtype=-1);
sum()//矩阵所有元素求和
determinant()//计算矩阵的行列式
//10.计算矩阵的特征值和特征向量;
//正定矩阵(positive definite matrix):矩阵的特征值都是正数;
//半正定矩阵(semi-definite matrix):矩阵的特征值都是非负数(正数和0);
//判断矩阵是否正定或者半正定就需要计算矩阵的特征值和特征向量,
eigen(myMat, eValuesMat, eVectorsMat);
//11.傅里叶变换和余弦变换
dct, idct正、逆离散余弦变换,idct同dct(src, dst, flags | DCT_INVERSE);
dft, idft正、逆离散傅立叶变换, idft同dft(src, dst, flags | DTF_INVERSE);
mulSpecturms()//两个傅立叶频谱间逐元素的乘法
//12.归一化
norm()//求范数,1-范数、2-范数、无穷范数
normalize()//标准化
//13.向量
magnitude()//计算向量的长度
phase()//相位计算,即两个向量之间的夹角
polarToCart()//已知角度和幅度,计算对应的二维向量
mahalanobis()//马氏距离,协方差的逆
//其他
trace()//计算矩阵的迹
calcCovarMatrix()//计算协方差阵
countNonZero()//计算矩阵中的非零元素个数,用于计算物体的像素或面积
setIdentity()设置单元矩阵
cartToPolar, polarToCart笛卡尔坐标与极坐标之间的转换
2. Mat子矩阵操作
2.1子矩阵创建
//1.使用Range定义ROI
Mat a=m(Range(i1, i2), Range(j1, j2)); //Range(i1,i2)包含i1不包含i2 行列编号从0开始
Mat b=m(Range::all(), Range(j1, j2)); //Range::all()表示所有行 [j1,j2]列
//2.使用Rect定义ROI
Mat a=m(Rect(200,200,300,400));
//示例
Mat src1 = Mat::zeros(Size(400, 400), CV_8UC3);
Rect rect(100, 100, 100, 100);
src1(rect) = Scalar(0, 0, 255);
2.2子矩阵赋值
//矩阵A的子矩阵都赋值为1个常数2
A(Range(row, row + n), Range(col, col + m)) = 3;
//将矩阵A赋值给矩阵B的1个子矩阵
A.copyTo(B(Range(row, row + n), Range(col, col + m)));
3. Mat矩阵变形
//1.变形
//参数cn:新的通道数;如果cn值为0表示变换前后通道数不变
//参数rows:新的行数;如果rows值为0表示变换后矩阵的行数不变
//该函数会为当前矩阵创建一个新的矩阵头(指针),不用复制矩阵数据.
//A要为单独矩阵,不能直接为矩阵的一部分。
A.reshape(int cn, int rows);
//2.合并
hconcat(A,B,dst1) 水平方向合并
vconcat(A,B,dst2) 垂直方向合并
//3.矩阵底部添加、删除元素
A.push_back(B); //B添加在A的底部,B可以是常数
A.pop_back(m); //从A的底部删除m行
参考
1. 原文链接:https://blog.csdn.net/qq_18150255/article/details/90648407