在《OpenCV Mat主要用法(1)》主要是详细分析了Mat类中的主要Method用法,可以了解到Mat中常用的创建,访问,变量等一些方法,但是有时候还远远不够。OpenCV Mat主要功能就是将图片信息统一保存到Mat 矩阵中,使之能够按照矩阵的方式进行各种算法的演进,但实际上Mat存储方式为矩阵,为了使用方便就应该提供各种常见的加减乘除矩阵式操作方式,如果每次让开发人员来自己实现两个矩阵的加减乘除操作,想想就是非常可怕。OpenCV提供了各种常见的数学表达式操作。
Mat是如何实现常见表达式操作
Mat实现常见表达式操作,是通过operator=重构来实现的,在《OpenCV Mat主要用法(1)》中Mat对operator=重构中有两个API,其中有一个重要的API:
在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;
}
运行结果:
常量与矩阵相加减用例:
#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;
}
运行结果:
矩阵符号取反:
#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;
}
运行结果:
矩阵相乘或相除:
#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;
}
运行结果:
矩阵乘以或者除以一个常数:
#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;
}
运行结果:
两个矩阵比较
#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;
}
运行结果:
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) |