OpenCV矩阵操作

14 篇文章 2 订阅
12 篇文章 1 订阅

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_LUGaussian elimination with the optimal pivot element chosen.
DECOMP_SVDsingular value decomposition (SVD) method; the system can be over-defined and/or the matrix src1 can be singular
DECOMP_EIGeigenvalue decomposition; the matrix src1 must be symmetrical
DECOMP_CHOLESKYCholesky LLT factorization; the matrix src1 must be symmetrical and positively defined
DECOMP_QRQR factorization; the system can be over-defined and/or the matrix src1 can be singular
DECOMP_NORMALwhile 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_8Uuchar(0,255)
CV_8Schar(-128,127)
CV_16Uushort(0,65535)
CV_16Sshort(-32768,32767)
CV_32Sint(-2147483648,2147483647)
CV_32Ffloat(-FLT_MAX,FLT_MAX,INF,NAN)
CV_64Fdouble(-DBL_MAX,DBL_MAX,INF,NAN)

多通道数据:

Mat数据类型C2C3C4C6
CV_8UVec2bVec3bVec4b
CV_16SVec2sVec3sVec4s
CV_32SVec2iVec3iVec4i
CV_32FVec2fVec3fVec4fVec6f
CV_64FVec2dVec3dVec4dVec6d

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_RELATIVEflag
NORM_MINMAXflag

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_ROWeach matrix row is sorted independently
SORT_EVERY_COLUMNeach matrix column is sorted independently; this flag and the previous one are mutually exclusive.
SORT_ASCENDINGeach matrix row is sorted in the ascending order.
SORT_DESCENDINGeach 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)
MahalanobisMahalanobis距离计算
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

  • 6
    点赞
  • 38
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值