在《OpenCV Mat主要用法(1)》主要是详细分析了Mat类中的主要Method用法,可以了解到Mat中常用的创建,访问,变量等一些方法,但是有时候还远远不够。OpenCV Mat主要功能就是将图片信息统一保存到Mat 矩阵中,使之能够按照矩阵的方式进行各种算法的演进,但实际上Mat存储方式为矩阵,为了使用方便就应该提供各种常见的加减乘除矩阵式操作方式,如果每次让开发人员来自己实现两个矩阵的加减乘除操作,想想就是非常可怕。OpenCV提供了各种常见的数学表达式操作。

Mat是如何实现常见表达式操作

Mat实现常见表达式操作,是通过operator=重构来实现的,在《OpenCV Mat主要用法(1)》中Mat对operator=重构中有两个API,其中有一个重要的API:

java opencv Mat 面积 opencv中mat的用法_java opencv Mat 面积

在API中有详细的说明 expr为支持常见的Mat 矩阵表达式,Mat是通过MatExpr类来实现常见的表达式。每次写Mat表达式时就相当于调用到了operator=重构函数,最后调用到了MatExpr类。OpenCV通过这种设计方式将其API与表达式进行了功能上完美隔离。在《Learning OpenCV3》:第四章“Images and Large Array Types”中的Matrix Expression:Algebra and cv:Mat部分中有明确的提到,感兴趣的读者可以读下原著。下面摘自其部分原话:

The result of the computation is finally placed in the destination array by operator=().However,  one important distinction is that this form of operator=() is not assigning a cv::Mat or a cv::Mat(as it might appear),but rather a cv::MatExpr(the expression itself) to a cv::mat.

Mat支持的常见的矩阵表达式

Mat支持的常见表达式如下:

Example

Description

m0 + m1, m0-m1

m0, m1为两个Mat矩阵,支持两个矩阵相加或相减

m0中相对应的矩阵位置值与m1中相对应的矩阵位置值相加或相减

m0+ s;m0-s;

s+mo; s-m1;

s为离散值,支持离散值与矩阵向加或相减,此时矩阵中每个值都相加或相减同一个s值

-m0

支持对矩阵中的每个值取符号相反

s*m0;m0*s

矩阵乘以一个s常数

m0.mul(m1); m0/m1

支持两个矩阵每个值相乘或相除

m0*m1

矩阵相乘

m0.inv(method)

支持矩阵的逆

m0.t()

支持矩阵转置

m0>m1;m0>=m1;m0 == m1;

m0<=m1; m0<m1

支持两个矩阵比较,比较的结果为0或者255

下面为几个简单例子:

两个矩阵相加或相减用例:

#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;


void main()
{
	Mat A(3, 3, CV_32FC1);
	Mat B(3, 3, CV_32FC1);
	
	A.at<float>(0, 0) = 1;
	A.at<float>(0, 1) = 2;
	A.at<float>(0, 2) = 3;
	A.at<float>(1, 0) = 4;
	A.at<float>(1, 1) = 5;
	A.at<float>(1, 2) = 6;
	A.at<float>(2, 0) = 1;
	A.at<float>(2, 1) = 2;
	A.at<float>(2, 2) = 3;


	B.at<float>(0, 0) = 3;
	B.at<float>(0, 1) = 2;
	B.at<float>(0, 2) = 1;
	B.at<float>(1, 0) = 6;
	B.at<float>(1, 1) = 5;
	B.at<float>(1, 2) = 4;
	B.at<float>(2, 0) = 1;
	B.at<float>(2, 1) = 2;
	B.at<float>(2, 2) = 3;
	cout << "A = "<<endl<<  A<< endl;
	cout << "B= "  <<endl<< B << endl;
	cout << "A+B = "  <<endl<< A+B << endl;
	cout << "A-B = " << endl << A - B << endl;

}

运行结果:

java opencv Mat 面积 opencv中mat的用法_MatExpr_02

常量与矩阵相加减用例:

 

#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;


void main()
{
	Mat A(3, 3, CV_32FC1);
	Mat B(3, 3, CV_32FC1);
	
	A.at<float>(0, 0) = 1;
	A.at<float>(0, 1) = 2;
	A.at<float>(0, 2) = 3;
	A.at<float>(1, 0) = 4;
	A.at<float>(1, 1) = 5;
	A.at<float>(1, 2) = 6;
	A.at<float>(2, 0) = 1;
	A.at<float>(2, 1) = 2;
	A.at<float>(2, 2) = 3;


	B.at<float>(0, 0) = 3;
	B.at<float>(0, 1) = 2;
	B.at<float>(0, 2) = 1;
	B.at<float>(1, 0) = 6;
	B.at<float>(1, 1) = 5;
	B.at<float>(1, 2) = 4;
	B.at<float>(2, 0) = 1;

	B.at<float>(2, 1) = 2;
	B.at<float>(2, 2) = 3;
	cout << "A = "<<endl<<  A<< endl;
	cout << "B= "  <<endl<< B << endl;
	cout << "A+B = "  <<endl<< A+2 << endl;
	cout << "A-B = " << endl << A - 2 << endl;

}

运行结果:

 

java opencv Mat 面积 opencv中mat的用法_#include_03

 矩阵符号取反:

#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;


void main()
{
	Mat A(3, 3, CV_32FC1);
	Mat B(3, 3, CV_32FC1);
	
	A.at<float>(0, 0) = 1;
	A.at<float>(0, 1) = 2;
	A.at<float>(0, 2) = 3;
	A.at<float>(1, 0) = 4;
	A.at<float>(1, 1) = 5;
	A.at<float>(1, 2) = 6;
	A.at<float>(2, 0) = 1;
	A.at<float>(2, 1) = 2;
	A.at<float>(2, 2) = 3;


	B.at<float>(0, 0) = 3;
	B.at<float>(0, 1) = 2;
	B.at<float>(0, 2) = 1;
	B.at<float>(1, 0) = 6;
	B.at<float>(1, 1) = 5;
	B.at<float>(1, 2) = 4;
	B.at<float>(2, 0) = 1;

	B.at<float>(2, 1) = 2;
	B.at<float>(2, 2) = 3;
	cout << "A = "<<endl<<  A<< endl;
	cout << "B= "  <<endl<< B << endl;
	cout << "-A = "  <<endl<< -A << endl;
	cout << "-B= " << endl << -B << endl;

}

运行结果:

java opencv Mat 面积 opencv中mat的用法_mat_04

矩阵相乘或相除:

 

#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;


void main()
{
	Mat A(3, 3, CV_32FC1);
	Mat B(3, 3, CV_32FC1);
	
	A.at<float>(0, 0) = 1;
	A.at<float>(0, 1) = 2;
	A.at<float>(0, 2) = 3;
	A.at<float>(1, 0) = 4;
	A.at<float>(1, 1) = 5;
	A.at<float>(1, 2) = 6;
	A.at<float>(2, 0) = 1;
	A.at<float>(2, 1) = 2;
	A.at<float>(2, 2) = 3;


	B.at<float>(0, 0) = 3;
	B.at<float>(0, 1) = 2;
	B.at<float>(0, 2) = 1;
	B.at<float>(1, 0) = 6;
	B.at<float>(1, 1) = 5;
	B.at<float>(1, 2) = 4;
	B.at<float>(2, 0) = 1;

	B.at<float>(2, 1) = 2;
	B.at<float>(2, 2) = 3;
	cout << "A = "<<endl<<  A<< endl;
	cout << "B= "  <<endl<< B << endl;
	cout << "A.mul(B) = "  <<endl<< A.mul(B)<< endl;
	cout << "A/B " << endl << A/B<< endl;

}

运行结果:

 

java opencv Mat 面积 opencv中mat的用法_#include_05

 矩阵乘以或者除以一个常数:

#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;


void main()
{
	Mat A(3, 3, CV_32FC1);
	Mat B(3, 3, CV_32FC1);
	
	A.at<float>(0, 0) = 1;
	A.at<float>(0, 1) = 2;
	A.at<float>(0, 2) = 3;
	A.at<float>(1, 0) = 4;
	A.at<float>(1, 1) = 5;
	A.at<float>(1, 2) = 6;
	A.at<float>(2, 0) = 1;
	A.at<float>(2, 1) = 2;
	A.at<float>(2, 2) = 3;


	B.at<float>(0, 0) = 3;
	B.at<float>(0, 1) = 2;
	B.at<float>(0, 2) = 1;
	B.at<float>(1, 0) = 6;
	B.at<float>(1, 1) = 5;
	B.at<float>(1, 2) = 4;
	B.at<float>(2, 0) = 1;

	B.at<float>(2, 1) = 2;
	B.at<float>(2, 2) = 3;
	cout << "A = "<<endl<<  A<< endl;
	cout << "B= "  <<endl<< B << endl;
	cout << "A*2 = "  <<endl<< A*2<< endl;
	cout << "B/2 " << endl << B/2<< endl;

}

运行结果:

java opencv Mat 面积 opencv中mat的用法_opencv_06

 两个矩阵比较

#include <stdio.h>
#include "opencv2/opencv.hpp"
#include "opencv2/highgui/highgui.hpp"
#include "opencv2/imgproc/imgproc.hpp"

using namespace cv;
using namespace std;


void main()
{
	Mat A(3, 3, CV_32FC1);
	Mat B(3, 3, CV_32FC1);
	
	A.at<float>(0, 0) = 1;
	A.at<float>(0, 1) = 2;
	A.at<float>(0, 2) = 3;
	A.at<float>(1, 0) = 4;
	A.at<float>(1, 1) = 5;
	A.at<float>(1, 2) = 6;
	A.at<float>(2, 0) = 1;
	A.at<float>(2, 1) = 2;
	A.at<float>(2, 2) = 3;


	B.at<float>(0, 0) = 3;
	B.at<float>(0, 1) = 2;
	B.at<float>(0, 2) = 1;
	B.at<float>(1, 0) = 6;
	B.at<float>(1, 1) = 5;
	B.at<float>(1, 2) = 4;
	B.at<float>(2, 0) = 1;

	B.at<float>(2, 1) = 2;
	B.at<float>(2, 2) = 3;
	cout << "A = "<<endl<<  A<< endl;
	cout << "B= "  <<endl<< B << endl;
	cout << "A>=B "  <<endl<< (A>=B)<< endl;
	

}

运行结果:

java opencv Mat 面积 opencv中mat的用法_MatExpr_07

MatExpr类

由上述分析可知,mat的矩阵表达式是通过MatExpr类来实现的 ,而MatExpr类中大部分的实现基本上都是通过C++的operator特性,通过对常用表达式重构来实现的,可以查看MatExpr类都重构了哪些常用的操作符

operator

Method

+ 加

CV_EXPORTS MatExpr operator + (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator + (const Mat& a, const Scalar& s)

CV_EXPORTS MatExpr operator + (const Scalar& s, const Mat& a)

CV_EXPORTS MatExpr operator + (const MatExpr& e, const Mat& m)

CV_EXPORTS MatExpr operator + (const Mat& m, const MatExpr& e)

CV_EXPORTS MatExpr operator + (const MatExpr& e, const Scalar& s)

CV_EXPORTS MatExpr operator + (const Scalar& s, const MatExpr& e)

CV_EXPORTS MatExpr operator + (const MatExpr& e1, const MatExpr& e2)

template<typename _Tp, int m, int n> static inline

MatExpr operator + (const Mat& a, const Matx<_Tp, m, n>& b

template<typename _Tp, int m, int n> static inline

MatExpr operator + (const Matx<_Tp, m, n>& a, const Mat& b)

-减

CV_EXPORTS MatExpr operator - (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator - (const Mat& a, const Scalar& s)

CV_EXPORTS MatExpr operator - (const Scalar& s, const Mat& a)

CV_EXPORTS MatExpr operator - (const MatExpr& e, const Mat& m)

CV_EXPORTS MatExpr operator - (const Mat& m, const MatExpr& e)

CV_EXPORTS MatExpr operator - (const MatExpr& e, const Scalar& s)

CV_EXPORTS MatExpr operator - (const Scalar& s, const MatExpr& e)

CV_EXPORTS MatExpr operator - (const MatExpr& e1, const MatExpr& e2)

template<typename _Tp, int m, int n> static inline

MatExpr operator - (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator - (const Matx<_Tp, m, n>& a, const Mat& b) 

CV_EXPORTS MatExpr operator - (const Mat& m)

CV_EXPORTS MatExpr operator - (const MatExpr& e)

*乘

注意:如果是两个矩阵,则做的是两个矩阵相乘,如果要两个矩阵每个对应位置的元素相乘则使用mul函数接口

CV_EXPORTS MatExpr operator * (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator * (const Mat& a, double s)

CV_EXPORTS MatExpr operator * (double s, const Mat& a)

CV_EXPORTS MatExpr operator * (const MatExpr& e, const Mat& m)

CV_EXPORTS MatExpr operator * (const Mat& m, const MatExpr& e)

CV_EXPORTS MatExpr operator * (const MatExpr& e, double s)

CV_EXPORTS MatExpr operator * (double s, const MatExpr& e)

CV_EXPORTS MatExpr operator * (const MatExpr& e1, const MatExpr& e2)

template<typename _Tp, int m, int n> static inline

MatExpr operator * (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator * (const Matx<_Tp, m, n>& a, const Mat& b)

/:除

CV_EXPORTS MatExpr operator / (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator / (const Mat& a, double s)

CV_EXPORTS MatExpr operator / (double s, const Mat& a)

CV_EXPORTS MatExpr operator / (const MatExpr& e, const Mat& m)

CV_EXPORTS MatExpr operator / (const Mat& m, const MatExpr& e)

CV_EXPORTS MatExpr operator / (const MatExpr& e, double s)

CV_EXPORTS MatExpr operator / (double s, const MatExpr& e)

CV_EXPORTS MatExpr operator / (const MatExpr& e1, const MatExpr& e2)

template<typename _Tp, int m, int n> static inline

MatExpr operator / (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator / (const Matx<_Tp, m, n>& a, const Mat& b)

<:小于

CV_EXPORTS MatExpr operator < (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator < (const Mat& a, double s)

CV_EXPORTS MatExpr operator < (double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator < (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator < (const Matx<_Tp, m, n>& a, const Mat& b)

<=:小于等于

CV_EXPORTS MatExpr operator <= (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator <= (const Mat& a, double s)

CV_EXPORTS MatExpr operator <= (double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator <= (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator <= (const Matx<_Tp, m, n>& a, const Mat& b)

==:等于

CV_EXPORTS MatExpr operator == (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator == (const Mat& a, double s)

CV_EXPORTS MatExpr operator == (double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator == (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator == (const Matx<_Tp, m, n>& a, const Mat& b)

!=:不等于

CV_EXPORTS MatExpr operator != (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator != (const Mat& a, double s)

CV_EXPORTS MatExpr operator != (double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator != (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator != (const Matx<_Tp, m, n>& a, const Mat& b)

>=:大于等于

CV_EXPORTS MatExpr operator >= (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator >= (const Mat& a, double s)

CV_EXPORTS MatExpr operator >= (double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator >= (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator >= (const Matx<_Tp, m, n>& a, const Mat& b)

>:大于

CV_EXPORTS MatExpr operator > (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator > (const Mat& a, double s)

CV_EXPORTS MatExpr operator > (double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator > (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator > (const Matx<_Tp, m, n>& a, const Mat& b)

&:与操作

CV_EXPORTS MatExpr operator & (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator & (const Mat& a, const Scalar& s)

CV_EXPORTS MatExpr operator & (const Scalar& s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator & (const Mat& a, const Matx<_Tp, m, n>& b) 

template<typename _Tp, int m, int n> static inline

MatExpr operator & (const Matx<_Tp, m, n>& a, const Mat& b)

|:或操作

CV_EXPORTS MatExpr operator | (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator | (const Mat& a, const Scalar& s)

CV_EXPORTS MatExpr operator | (const Scalar& s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator | (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator | (const Matx<_Tp, m, n>& a, const Mat& b)

^:异或

CV_EXPORTS MatExpr operator ^ (const Mat& a, const Mat& b)

CV_EXPORTS MatExpr operator ^ (const Mat& a, const Scalar& s)

CV_EXPORTS MatExpr operator ^ (const Scalar& s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr operator ^ (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr operator ^ (const Matx<_Tp, m, n>& a, const Mat& b)

~:取反

CV_EXPORTS MatExpr operator ~(const Mat& m)

min:取两者最小值

CV_EXPORTS MatExpr min(const Mat& a, const Mat& b)

CV_EXPORTS MatExpr min(const Mat& a, double s)

CV_EXPORTS MatExpr min(double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr min (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr min (const Matx<_Tp, m, n>& a, const Mat& b)

max:两者最大值

CV_EXPORTS MatExpr max(const Mat& a, const Mat& b)

CV_EXPORTS MatExpr max(const Mat& a, double s)

CV_EXPORTS MatExpr max(double s, const Mat& a)

template<typename _Tp, int m, int n> static inline

MatExpr max (const Mat& a, const Matx<_Tp, m, n>& b)

template<typename _Tp, int m, int n> static inline

MatExpr max (const Matx<_Tp, m, n>& a, const Mat& b) 

abs:两者差的绝对值

CV_EXPORTS MatExpr abs(const Mat& m)

CV_EXPORTS MatExpr abs(const MatExpr& e)

t

 MatExpr t()

inv

MatExpr inv(int method = DECOMP_LU)

mul

 MatExpr mul(const Mat& m, double scale=1)

cross

Mat cross(const Mat& m)

dot

double dot(const Mat& m)