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

时间: 2024-10-12 21:25:25

OpenCV—基本矩阵操作与示例的相关文章

OpenCV &mdash;&mdash; 矩阵操作

多通道的矩阵 -- 通道是连续的!! 要将指向该数据类型的指针移动到下一通道,我们只需要将其增加1.如果想访问下一个"像素"或者元素集,则需要一定的偏移量 矩阵的step元素是矩阵中行的长度,单位为字节.   #include "cv.h" #include "highgui.h" #include <IOSTREAM.H> int main(int argc,char** argv) { float vals[]={0.85,-0.

关于SVN的操作批处理示例

关于SVN的操作批处理示例 为了一句话:不要动手做机器能够做的事情. 天天工作用svn,更新啥的打开目录啥的动作天天在重复.每次写些命令也蛮无聊的,不说了,看下面: 1 @echo off 2 rem 显示部分 3 @echo 注 意 事 项 4 @echo ************************************************************************ 5 @echo 可以精简并通过计划任务来制定自动执行,运行前请检查下面目录: 6 @echo.

AD帐户操作C#示例代码(一)——导入用户信息

最近写了一个AD帐户导入的小工具(为啥写作“帐”户呢?),跟大家分享下相关代码,欢迎各位高手指教! 首先,我准备一个这样的Excel文件作为导入模版,并添加了一些测试数据. 然后,我打开Visual Studio 2012,新建一个Windows窗体应用程序.在主窗体界面,我放了一些Label.TextBox.Button控件,还有一个ProgressBar. 开始写代码.首先写从Excel里读取数据的方法. private static async Task<DataTable> GetTa

MySql的事务操作与示例

事务就是一个逻辑工作单元的一系列步骤.事务是用来保证数据操作的安全性 事务的特征: Atomicity(原子性) Consistency(稳定性,一致性) Isolation(隔离性) Durability(可靠性) [事务只针对对数据数据产生影响的语句有效] show engines  //查看mysql锁支持的数据引擎 MyISAM不支持事物,InnoDB支持事物 默认情况下,MySQL将以自动提交模式运行,这意味着没一条小命令都将当做一个只有一条命令的事物来执行. 如果要让mysql支持支

AD帐户操作C#示例代码(二)——检查密码将过期的用户

本文接着和大家分享AD帐户操作,这次开发一个简单的检查密码将过期用户的小工具. 首先,新建一个用户实体类,属性是我们要取的用户信息. public class UserInfo { /// <summary> /// sAM帐户名称 /// </summary> public string SamAccountName { get; set; } /// <summary> /// 名称 /// </summary> public string Name {

DBI模块操作数据库示例

Perl中一个很重要的模块就是DBI模块(Perl Database Interface,数据库接口).DBI模块为很多不同的数据库提供了一个统一的接口.Perl通过此接口可以很容易对数据库进行操作.结构图如下: 下面说下Perl如何对MySQL数据库进行操作. 1. 首先要确保Perl及MySQL数据库已经安装.然后用cpan或者是ppm图形化界面来安装. cpan> install DBI #安装数据库模块 cpan> install DBD::mysql #安装数据库驱动 2. 然后准备

Oracle数据库用EF操作的示例

Using EF Oracle Sample Provider with EDM Designer  (from msdn) Many people are asking if it is possible to use EFOracleProvider with EDM Designer in Visual Studio 2008 SP1. The answer is yes, but because the sample doesn't include a DDEX provider req

Python操作SQLServer示例

本文主要是Python操作SQLServer示例,包括执行查询及更新操作(写入中文). 需要注意的是:读取数据的时候需要decode('utf-8'),写数据的时候需要encode('utf-8'),这样就可以避免烦人的中文乱码或报错问题. Python操作SQLServer需要使用pymssql模块,使用pip install pymssql安装即可. 此外代码中使用的封装MSSQL类是从网上搜索到的,直接用即可. # -*- coding:utf-8 -*- import pymssql c

OpenCV读写操作

OpenCV读取一副图片 imread( const String& filename, int flags = IMREAD_COLOR ); 参数1.文件名(路径与文件名,如果文件在目录中可以直接使用文件名即可) 参数2.读取方式 flags > 0  返回一个3通道的彩色图像 flags = 0  返回一个灰度图像 flags < 0  返回包含Alpha通道的加载图像 OpenCV写入一副图片 //如果目标文件夹内有同名文件则不执行任何操作, 包括下方的任何操作 imwrite