OpenCV—基本矩阵操作与示例
OpenCV的基本矩阵操作与示例
OpenCV中的矩阵操作非常重要,本文总结了矩阵的创建、初始化以及基本矩阵操作,给出了示例代码,主要内容包括:
- 创建与初始化
- 矩阵加减法
- 矩阵乘法
- 矩阵转置
- 矩阵求逆
- 矩阵非零元素个数
- 矩阵均值与标准差
- 矩阵全局极值及位置
- 其他矩阵运算函数列表
1. 创建与初始化矩阵
1.1 数据类型
建立矩阵必须要指定矩阵存储的数据类型,图像处理中常用的几种数据类型如下:
-
CV_8UC1
// 8位无符号单通道
-
CV_8UC3
// 8位无符号3通道
-
CV_8UC4
-
CV_32FC1
// 32位浮点型单通道
-
CV_32FC3
// 32位浮点型3通道
-
CV_32FC4
包括数据位深度8位、32位,数据类型U:uchar、F:float型以及通道数C1:单通道、C3:三通道、C4:四通道。
1.2 基本方法
我们可以通过载入图像来创建Mat类型矩阵,当然也可以直接手动创建矩阵,基本方法是指定矩阵尺寸和数据类型:
-
// 基本方法
-
cv::
Mat a(cv::Size(5,5),CV_8UC1);
// 单通道
-
cv::Mat b = cv::Mat(cv::Size(
5,
5),CV_8UC3);
//3通道每个矩阵元素包含3个uchar值
-
cout<<
"a = "<<
endl<<a<<
endl<<
endl;
-
cout<<
"b = "<<
endl<<b<<
endl<<
endl;
-
system(
"pause");
运行结果:
3通道矩阵中,一个矩阵元素包含3个变量。
1.3 初始化方法
上述方法不初始化矩阵数据,因此将出现随机值。如果想避免这种情况,可使用Mat类的几种初始化创建矩阵的方法:
-
// 初始化方法
-
cv::Mat mz = cv::Mat::zeros(cv::Size(
5,
5),CV_8UC1);
// 全零矩阵
-
cv::Mat mo = cv::Mat::ones(cv::Size(
5,
5),CV_8UC1);
// 全1矩阵
-
cv::Mat me = cv::Mat::eye(cv::Size(
5,
5),CV_32FC1);
// 对角线为1的对角矩阵
-
cout<<
"mz = "<<
endl<<mz<<
endl<<
endl;
-
cout<<
"mo = "<<
endl<<mo<<
endl<<
endl;
-
cout<<
"me = "<<
endl<<me<<
endl<<
endl;
运行结果: 2. 矩阵运算
2.1 基本概念
OpenCV的Mat类允许所有的矩阵运算。
2.2 矩阵加减法
我们可以使用"+"和"-"符号进行矩阵加减运算。
-
cv::Mat a= Mat::eye(Size(
3,
2), CV_32F);
-
cv::Mat b= Mat::ones(Size(
3,
2), CV_32F);
-
cv::Mat c= a+b;
-
cv::Mat d= a-b;
2.3 矩阵乘法
使用"*"号计算矩阵与标量相乘,矩阵与矩阵相乘(必须满足矩阵相乘的行列数对应规则)
-
Mat m1= Mat::eye(
2,
3, CV_32F);
//使用cv命名空间可省略cv::前缀,下同
-
Mat m2= Mat::ones(
3,
2, CV_32F);
-
cout<<
"m1 = "<<
endl<<m1<<
endl<<
endl;
-
cout<<
"m2 = "<<
endl<<m2<<
endl<<
endl;
-
// Scalar by matrix
-
cout <<
"\nm1.*2 = \n" << m1*
2 <<
endl;
-
// matrix per element multiplication
-
cout <<
"\n(m1+2).*(m1+3) = \n" << (m1+
1).mul(m1+
3) <<
endl;
-
// Matrix multiplication
-
cout <<
"\nm1*m2 = \n" << m1*m2 <<
endl;
2.4 矩阵转置
矩阵转置是将矩阵的行与列顺序对调(第i行转变为第i列)形成一个新的矩阵。OpenCV通过Mat类的t()函数实现。
-
// 转置
-
Mat m1= Mat::eye(
2,
3, CV_32F);
-
Mat m1t = m1.t();
-
cout<<
"m1 = "<<
endl<<m1<<
endl<<
endl;
-
cout<<
"m1t = "<<
endl<<m1t<<
endl<<
endl;
-
system(
"pause");
运行结果: 2.5 求逆矩阵
逆矩阵在某些算法中经常出现,在OpenCV中通过Mat类的inv()方法实现
-
// 求逆
-
Mat meinv = me.inv();
-
cout<<
"me = "<<
endl<<me<<
endl<<
endl;
-
cout<<
"meinv = "<<
endl<<meinv<<
endl<<
endl;
-
system(
"pause");
单位矩阵的逆就是其本身。
2.6 计算矩阵非零元素个数
计算物体的像素或面积常需要用到计算矩阵中的非零元素个数,OpenCV中使用countNonZero()函数实现。
-
// 非零元素个数
-
int nonZerosNum = countNonZero(me);
// me为输入矩阵或图像
-
cout<<
"me = "<<
endl<<me<<
endl;
-
cout<<
"me中非零元素个数 = "<<nonZerosNum<<
endl<<
endl;
-
system(
"pause");
2.7 均值和标准差
OpenCV提供了矩阵均值和标准差计算功能,可以使用meanStdDev(src,mean,stddev)函数实现。参数
- src – 输入矩阵或图像
- mean – 均值,OutputArray
- stddev – 标准差,OutputArray
-
// 均值方差
-
Mat mean;
-
Mat stddev;
-
meanStdDev(me, mean, stddev);
//me为前文定义的5×5对角阵
-
cout<<
"mean = "<<mean<<
endl;
-
cout<<
"stddev = "<<stddev<<
endl;
-
system(
"pause");
运行结果:
需要说明的是,如果src是多通道图像或多维矩阵,则函数分别计算不同通道的均值与标准差,因此返回值mean和stddev为对应维度的向量。
-
Mat mean3;
-
Mat stddev3;
-
Mat m3(cv::Size(5,5),CV_8UC3,Scalar(255,200,100));
-
cout<<
"m3 = "<<
endl<<m3<<
endl<<
endl;
-
meanStdDev(m3, mean3, stddev3);
-
cout<<
"mean3 = "<<mean3<<
endl;
-
cout<<
"stddev3 = "<<stddev3<<
endl;
-
system(
"pause");
多通道矩阵运算结果:
2.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 = "<<minVal<<
endl;
-
cout<<
"max value = "<<maxVal<<
endl;
-
cout<<
"minPt = ("<<minPt.x<<
","<<minPt.y<<
")"<<
endl;
-
cout<<
"maxPt = ("<<maxPt.x<<
","<<maxPt.y<<
")"<<
endl;
-
cout<<
endl;
-
-
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();
运行结果: 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 | 两个傅立叶频谱间逐元素的乘法 |
上表引自:http://blog.sina.com.cn/s/blog_7908e1290101i97z.html
转载请注明出处(本文更新链接):http://blog.csdn.net/iracer/article/details/51296631