文章目录
1.矩阵创建
矩阵尺寸大小:就是m行n列;size::Size(n cols,m rows);
矩阵数据类型:深度8/32位,类型uchar/float,通道数1/3/4;
CV_8UC1// 8位无符号单通道
CV_8UC3// 8位无符号3通道
CV_8UC4// 8位无符号4通道
CV_32FC1// 32位浮点型单通道
CV_32FC3// 32位浮点型3通道
CV_32FC4// 32位浮点型4通道
#include <opencv2/opencv.hpp>
#include <iostream>
using namespace cv;
using namespace std;
int main()
{
//构造函数1:cv::Mat::Mat(int rows,int cols,int type)
//Mat (int rows, int cols, int type, const Scalar &s)
Mat m0(2, 2, CV_32FC3);
cout << "m0 = " << m0 << endl;
//Mat m0(10, 10, CV_32FC3, Scalar(255, 255, 255));
//构造函数2:cv::Mat::Mat(Size size,int type )
//Mat (Size size, int type, const Scalar &s)
Mat m1(Size(3, 3), CV_8UC1);//单通道
cout << "m1 = " << m1 << endl;
//Mat m2 = Mat(Size(3, 3), CV_8UC3);//3通道
//cout << "m2 = " << m2 << endl;
//构造函数3:cv::Mat::Mat(const Mat & m)
Mat m3(m1);
return 0;
}
2.矩阵初始化
int main()
{
//1. 特殊矩阵创建
Mat mz = Mat::zeros(Size(5,5),CV_8UC1);//全0矩阵
Mat mo = Mat::ones(Size(5,5),CV_8UC1);//全1矩阵
Mat me = Mat::eye(Size(5,5),CV_32FC1);//对角线为1的对角矩阵
cout<<"mz = "<<mz<<endl;
/*mz=[0,0,0;
0,0,0;
0,0,0]
*/
cout<<"mo = "<<mo<<endl;
/*mo=[1,1,1;
1,1,1;
1,1,1]
*/
cout<<"me = "<<me<<endl;
/*me=[1,0,0;
0,1,0;
0,0,1]
*/
//2. 给定初始类型/初始值
Mat m1 = (Mat_<double>(3, 3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
}
3.矩阵转置(t())
//由Mat类t()函数实现:
int main()
{
Mat m = Mat::eye(2,3,CV_32FC1);
cout<<"m = \n "<<m<<endl;
Mat mt = m.t();
cout<<"mt = \n "<<mt<<endl;
}
/*输出
m =
[1, 0, 0;
0, 1, 0]
mt =
[1, 0;
0, 1;
0, 0]
*/
4.矩阵求逆(inv)
有两种方法:
①伴随阵法:inv(A)=(1/|A|)×A* ;
其中inv(A)表示矩阵A的逆矩阵,|A|为矩阵A的行列式的值,A*为矩阵A的伴随矩阵。
②行初等变换法:(A|E)经过初等变换得到(E|A^(-1));
【注】:初等变化只用行(列)运算,不能用列(行)运算,E为单位矩阵;
Mat矩阵的逆由inv()函数实现:
MatExpr cv::Mat::inv ( int method = DECOMP_LU) const
method:
Enumerator | |
---|---|
DECOMP_LU | Gaussian elimination with the optimal pivot element chosen. |
DECOMP_SVD | singular value decomposition (SVD) method; the system can be over-defined and/or the matrix src1 can be singular |
DECOMP_EIG | eigenvalue decomposition; the matrix src1 must be symmetrical |
DECOMP_CHOLESKY | Cholesky LLT factorization; the matrix src1 must be symmetrical and positively defined |
DECOMP_QR | QR factorization; the system can be over-defined and/or the matrix src1 can be singular |
DECOMP_NORMAL | while all the previous flags are mutually exclusive, this flag can be used together with any of the previous; it means that the normal equations src1T⋅src1⋅dst=src1Tsrc2 are solved instead of the original system src1⋅dst=src2 |
int main()
{
Mat m1 = Mat::eye(3,3,CV_32FC1);
cout<<"m1 = \n "<<m1<<endl;
Mat m1inv = m1.inv();
cout<<"m1inv = \n "<<m1inv<<endl;
}
5.矩阵元素访问
int main()
{
Mat m1 = Mat::eye(3, 3, CV_32FC1);
//1. m.rows 矩阵行数 m.cols 矩阵列数
cout << "size = \n " << m1.rows<<","<<m1.cols << endl;
//2. m.row(i) 取第i行 行编号从0开始,生成新的矩阵
Mat m1row = m1.row(1);
//3. m.col(j) 取第i列 列编号从0开始,生成新的矩阵
Mat m1col = m1.col(2);
cout << "m1row = \n " << m1row << endl<<
"m1col = \n " << m1col << endl;
cout << m1row.size() << endl <<
m1col.size() << endl;
//4.Mat的成员函数at<>()- _Tp & at (int row, int col)
//5.Mat的通道数
cout << "channels:" << m1.channels() << endl;
//6.维数
cout << "dims:" << m1.dims << endl;
//7.Mat的成员函数ptr<>()
return 0;
}
ptr<>()
cv::Mat m = cv::Mat(4, 6, CV_8UC1);
//指向第一行的指针
uchar * data00 = m.ptr<uchar>(0);
//指向第二行的指针
uchar * data10 = m.ptr<uchar>(1);
//指向第一行第二个元素
uchar data01 = m.ptr<uchar>(0)[1];
图像矩阵遍历:
int x,y;
//计算图像一行需要被赋值的个数
int rowLength = image.cols*image.channels();
for(y=0;y<image.rows;y++)
{
//获取第行的起始地址
uchar* data = image.ptr<uchar>(y);
//对第y行逐个赋值
for(x=0;x<rowLength;x++)
{
*data++=255;
}
}
图像矩阵遍历,包含通道的操作:
uchar R, G, B;
for (int i = 0; i < image.rows; i++)
{
Vec3b* data = image.ptr<Vec3b>(i);
for (int j = 0; j < image.cols; j++)
{
B = data[j][0];
G = data[j][1];
R = data[j][2];
}
}
at<>()
m.at(i,j) 访问矩阵第(i,j) 注意矩阵A的类型,否则异常或取值出错 如:A为CV_32CF1时,type为int型时,所取值为异常值,不是矩阵值。
单通道数据:
Mat数据类型 | C++基本数据类型 | 取值范围 |
---|---|---|
CV_8U | uchar | (0,255) |
CV_8S | char | (-128,127) |
CV_16U | ushort | (0,65535) |
CV_16S | short | (-32768,32767) |
CV_32S | int | (-2147483648,2147483647) |
CV_32F | float | (-FLT_MAX,FLT_MAX,INF,NAN) |
CV_64F | double | (-DBL_MAX,DBL_MAX,INF,NAN) |
多通道数据:
Mat数据类型 | C2 | C3 | C4 | C6 |
---|---|---|---|---|
CV_8U | Vec2b | Vec3b | Vec4b | |
CV_16S | Vec2s | Vec3s | Vec4s | |
CV_32S | Vec2i | Vec3i | Vec4i | |
CV_32F | Vec2f | Vec3f | Vec4f | Vec6f |
CV_64F | Vec2d | Vec3d | Vec4d | Vec6d |
https://blog.csdn.net/guo1988kui/article/details/78094963
//单应矩阵求解
cv::Mat A(2*N,9,CV_32F); // 2N*9
for(int i=0; i<N; i++)
{
const float u1 = vP1[i].x;
const float v1 = vP1[i].y;
const float u2 = vP2[i].x;
const float v2 = vP2[i].y;
A.at<float>(2*i,0) = 0.0;
A.at<float>(2*i,1) = 0.0;
A.at<float>(2*i,2) = 0.0;
A.at<float>(2*i,3) = -u1;
A.at<float>(2*i,4) = -v1;
A.at<float>(2*i,5) = -1;
A.at<float>(2*i,6) = v2*u1;
A.at<float>(2*i,7) = v2*v1;
A.at<float>(2*i,8) = v2;
A.at<float>(2*i+1,0) = u1;
A.at<float>(2*i+1,1) = v1;
A.at<float>(2*i+1,2) = 1;
A.at<float>(2*i+1,3) = 0.0;
A.at<float>(2*i+1,4) = 0.0;
A.at<float>(2*i+1,5) = 0.0;
A.at<float>(2*i+1,6) = -u2*u1;
A.at<float>(2*i+1,7) = -u2*v1;
A.at<float>(2*i+1,8) = -u2;
}
6. 行列式(determinant)
//double cv::determinant (InputArray mtx)
Mat m = Mat::eye(Size(2,2), CV_32FC1);
cout<< cv::determinant(m)<<endl;
矩阵类型只能是CV_32FC1 or CV_64FC1 ;行列相等
7.矩阵复制(clone/copyTo)
Mat m2 = m1.clone();//完全复制
Mat m3;
m1.copyTo(m3);//传递矩阵头,另外赋值运算符和复制构造函数 (构造函数)也只复制头
8.矩阵行列的提取(rowRange/colRange)
int main()
{
Mat m = (Mat_<double>(3,3) << 0, -1, 0, -1, 5, -1, 0, -1, 0);
cout << "m=" << endl;
cout << m << endl;
//行选
Mat row = m.rowRange(1,3).clone();
cout << "row=" << endl;
cout << row << endl;
//列选
Mat col = m.colRange(1,3).clone();
cout << "col=" << endl;
cout << col << endl;
//行列
Mat rc = m.rowRange(1,3).colRange(1,3);
cout << "rc=" << endl;
cout << rc << endl;
/*ORB_SLAM2
cv::Mat P2(3,4,CV_32F);
R.copyTo(P2.rowRange(0,3).colRange(0,3));
t.copyTo(P2.rowRange(0,3).col(3));*/
}
/*
m=
[0, -1, 0;
-1, 5, -1;
0, -1, 0]
row=
[-1, 5, -1;
0, -1, 0]
col=
[-1, 0;
5, -1;
-1, 0]
rc=
[5, -1;
-1, 0]
*/
9.对角矩阵(diag)
//提取或创建矩阵对角线
Mat m = (Mat_<double>(3,3) << -1, -1, 0, 0, 5, -1, 0, 0, 0);
cout << "m=" << endl;
cout << m << endl;
//返回特征值组成的向量
cout<<m.diag()<<endl;
//把特征值组成的向量生成矩阵
cout << Mat::diag(m.diag()) << endl;
//ORB_SLAM2:u*cv::Mat::diag(w)*vt;
/*
m=
[-1, -1, 0;
0, 5, -1;
0, 0, 0]
[-1;
5;
0]
[-1, 0, 0;
0, 5, 0;
0, 0, 0]
*/
10.矩阵重塑(reshape)
//1. m.reshape(int cn, int rows);
vt.row(8).reshape(0, 3);
//新的矩阵尺寸与旧的矩阵尺寸不合时重新分配矩阵的数据空间
//2. .create函数
m.create(2,2,CV_8UC2);
11.范数(cv::norm)
double cv::norm (InputArray src1, int normType=NORM_L2, InputArray mask=noArray())
enum cv::NormTypes:
Enumerator | |
---|---|
NORM_INF | |
NORM_L1 | |
NORM_L2 | |
NORM_L2SQR | |
NORM_HAMMING | |
NORM_HAMMING2 | |
NORM_TYPE_MASK | |
NORM_RELATIVE | flag |
NORM_MINMAX | flag |
12.对Mat进行排序
/*void cv::sort ( InputArray src,
OutputArray dst,int flags )
*/
Mat m1 = (Mat_<uchar>(3, 3) << 10, 5, 6, 2, 4, 3, 8, 9, 7);
Mat m2 = m1.reshape(1, 9);
cv::sort(m2, m2, SORT_EVERY_COLUMN + CV_SORT_ASCENDING);
cout << m1 << endl;
cv::sort(m1, m1, SORT_EVERY_COLUMN + CV_SORT_ASCENDING);
cout << m1 << endl;
cout << m2<<endl;
flags:
Enumerator | |
---|---|
SORT_EVERY_ROW | each matrix row is sorted independently |
SORT_EVERY_COLUMN | each matrix column is sorted independently; this flag and the previous one are mutually exclusive. |
SORT_ASCENDING | each matrix row is sorted in the ascending order. |
SORT_DESCENDING | each matrix row is sorted in the descending order; this flag and the previous one are also mutually exclusive. |
sortid返回是大小的索引:
/*
void cv::sortIdx ( InputArray src,
OutputArray dst,int flags )
*/
Mat m1 = (Mat_<uchar>(3, 3) << 1, 5, 6, 2, 4, 3, 8, 9, 7);
Mat m2(m1);
//sort(m2, m2, CV_SORT_EVERY_ROW + CV_SORT_ASCENDING);
sortIdx(m1, m2, SORT_EVERY_COLUMN + SORT_ASCENDING);
13.矩阵其他操作
OpenCV - Operations on Arrays | |
---|---|
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 |
13表引自:http://blog.sina.com.cn/s/blog_7908e1290101i97z.html
参考
https://jingyan.baidu.com/article/cbcede077e58be02f40b4ddc.html
https://docs.opencv.org/3.3.0/d3/d63/classcv_1_1Mat.html
http://blog.sina.com.cn/s/blog_7908e1290101i97z.html
https://blog.csdn.net/weixin_40710375/article/details/94435225
https://blog.csdn.net/sinat_29089097/article/details/75533538