OpenCV从入门到精通(二) ——构造Mat、操作符重载

在OpenCV中,图像数据采用Mat进行表示。学会Mat的基本操作,是OpenCV的基础。
图像可以用二维矩阵表示,因此,可以把Mat看出一个二维矩阵。单通道图像是一个二维矩阵,三通道图像是三个二维矩阵。构造Mat的方式有很多种,下面分别介绍各种构造Mat数据的方式。另外,对于Mat数据的操作符重载主要是指加减乘除操作,这是最基本的Mat数据操作方式。

一、利用Mat类的构造函数来构造Mat数据

OpenCV的Mat类是最基本的图像处理数据类型,其中的构造函数可以用于构造Mat数据,这种方式主要用于构造比较小的矩阵。Mat构造函数有下列形式:
Mat();
Mat(int rows, int cols, int type);
Mat(Size size, int type);
Mat(int rows, int cols, int type, const Scalar& s);
Mat(Size size, int type, const Scalar& s);
Mat(int ndims, const int* sizes, int type);
Mat(const std::vector& sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
Mat(const std::vector& sizes, int type, const Scalar& s);
Mat(const Mat& m);
Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP);
Mat(Size size, int type, void* data, size_t step=AUTO_STEP);
Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0);
Mat(const std::vector& sizes, int type, void* data, const size_t* steps=0);
Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all());
Mat(const Mat& m, const Rect& roi);
Mat(const Mat& m, const Range* ranges);
Mat(const Mat& m, const std::vector& ranges);
上面各种形式的构造函数使用方法都差不多,需要弄清楚每个参数的含义,然后传入对应的参数就可以了。
参数:
rows:行数
cols:列数
type:数据类型
size:矩阵的高宽
s:构造Mat时可以给定初始值初始值
ndims:维度
data:数据指针,用于指定 Mat 对象的存储数据
step:可选参数,用于指定每行像素数据的步长
rowRange:指定已有Mat数据的行的范围
colRange:指定已有Mat数据的列的范围
roi:指定已有Mat数据的已有ROI矩形区域
ranges:指定已有Mat数据的行列范围
在c++中利用构造函数构造Mat的例子如下:

Mat ConstructMat=(Mat_<uchar>(3,3)<<1,2,3,4,5,6,7,8,9);

表示构造了一个ucahr数据类型的3×3大小的Mat数据类型,并且赋了初始值。
在python中可以使用cv2.Mat()的方式构造,但是如果在构造时赋初始值,一般不采用这样方式,而是采用下面这种方式:

ConstructMat = np.array((np.array([1,2,3,4,5,6,7,8,9]).reshape((3,3))), dtype = np.uint8)

另外,在emgucv和opencvsharp中可以采用下面的方式进行构造。
EmguCV:

Mat ConstructMat = new Mat(3,3,DepthType.Cv8U, 1);
byte[] ConstructMatData =new byte[]{1,2,3,4,5,6,7,8,9};
ConstructMat.SetTo(ConstructMatData);

OpenCVSharp:

Mat ConstructMat = new Mat(3,3,MatType.CV_8U, 1);
byte[] ConstructMatData =new byte[]{1,2,3,4,5,6,7,8,9};
Marshal.Copy(ConstructMatData,0,ConstructMat.Data,9);

对于其它构造函数的使用方式,也是类似的使用方法。在此就不再详述。

二、几种特殊的Mat矩阵

在OpenCV中,提供了几种特殊的Mat矩阵,分别是全“0”矩阵,全“1”矩阵,单位矩阵。其构造方式如下:

1、全“0”矩阵

使用函数zeros构造,有以下几种方式:
static MatExpr zeros(int rows, int cols, int type);
static MatExpr zeros(Size size, int type);
static MatExpr zeros(int ndims, const int* sz, int type);
参数:
Rows:行数
Cols:列数
type:数据类型
size:Mat行列大小
ndims:数组的维度
sz:指定数组的形状的整数数组。
C++中使用方法:

Mat ZerosMat=Mat::zeros(Size(3,3),CV_8U);

Python中通常使用np.zeros,使用方法:

ZerosMat=np.zeros((3,3), dtype = np.uint8)

EmguCV中使用方法:

Mat ZerosMat = Mat.Zeros(3,3,DepthType.Cv8U, 1);

OpenCVSharp中使用方法:

Mat ZerosMat = Mat.Zeros(3,3,MatType.CV_8UC1);

2、全“1”矩阵

使用函数ones构造,和zeros函数类似,有以下几种方式:
static MatExpr ones(int rows, int cols, int type);
static MatExpr zeros(Size size, int type);
static MatExpr ones(int ndims, const int* sz, int type);
参数:
Rows:行数
Cols:列数
type:数据类型
size:Mat行列大小
ndims:数组的维度
sz:指定数组的形状的整数数组。
C++中使用方法:

Mat OnesMat=Mat::ones(Size(3,3),CV_8U);

Python中通常使用np.ones,使用方法:

OnesMat=np.ones((3,3), dtype = np.uint8)

EmguCV中使用方法:

Mat OnesMat = Mat.Ones(3,3,DepthType.Cv8U, 1);

OpenCVSharp中使用方法::

Mat OnesMat = Mat.Ones(3,3,MatType.CV_8UC1);

3、单位矩阵

使用函数eye构造,和zeros函数类似,有以下几种方式:
static MatExpr eye(int rows, int cols, int type);
static MatExpr eye(Size size, int type);
参数:
Rows:行数
Cols:列数
type:数据类型
size:Mat行列大小
C++中使用方法:

Mat EyeMat=Mat::eye(Size(3,3),CV_8U);

Python中通常使用np.eye,使用方法:

EyeMat=np.eye(3,dtype =  np.uint8)

EmguCV中使用方法:

Mat EyeMat = Mat.Eye(3,3,DepthType.Cv8U, 1);

OpenCVSharp中使用方法::

Mat EyeMat = Mat.Eye(3,3,MatType.CV_8UC1);

三、利用已有的Mat数据来构造Mat矩阵

这种方式是使用非常多的,常见的选择图像中的某个矩形ROI区域,就可以采用这种方式,使用的函数主要是colRang、rowRange、Range三个。表示选择部分列和行来构造Mat数据。具体使用方式如下:
C++:

Mat ReadImage=imread("E:/TestImage/data/apple.jpg",1);
Mat ColRangeImage=ReadImage(100,200);
Mat RowRangeImage=ReadImage(100,200);
Mat RangeImage=ReadImage(Range(100,200),Range(100,200));

Python:

#如果支持中文路径,可以采用以下方式
#ReadImage=cv2.imread("E:/TestImage/data/apple.jpg",1)
#如果不支持中文,请采用以下方式
ReadImage = cv2.imdecode(np.fromfile("E:/TestImage/data/apple.jpg", dtype =np.uint8),1)
ColRangeImage=ReadImage[:,100:200]
RowRangeImage=ReadImage[100:200,:]
RangeImage=ReadImage[100:200,100:200]

EmguCV:

Mat ReadImage=CvInvoke.Imread("E:/TestImage/data/apple.jpg",(ImreadModes)1);
Mat ColRangeImage=  new Mat(ReadImage,Range.All,new Range(100,200));
Mat RowRangeImage=  new Mat(ReadImage,new Range(100,200),Range.All);
Mat RangeImage=  new Mat(ReadImage,new Range(100,200),new Range(100,200));

OpenCVSharp:

Mat ReadImage= Cv2.ImRead("E:/TestImage/data/apple.jpg",(ImreadModes)1);
Mat ColRangeImage=  new Mat(ReadImage,Range.All,new Range(100,200));
Mat RowRangeImage=  new Mat(ReadImage,new Range(100,200),Range.All);
Mat RangeImage=  new Mat(ReadImage,new Range(100,200),new Range(100,200));

上面的例子是从以打开的图像中选择部分行或列来构造Mat数据,也可以采用该方式来选择图像中的矩形感兴趣区域,得到的结果图像如下:
原图描述
选择100到200列
选择100到200行
选择100到200列和100到200行

四、Mat数据的操作符重载:加减乘除

Mat数据的加减乘除操作可以看作是一些数字的数学运算,和常规的数字之间的加减乘除是类似的,需要注意的是乘法运算是Mat和一个数字之间进行运算,如果需要两个Mat数据之间进行乘法运算,需要额外进行一些处理,
以下是图像Mat数据的加减乘除运算示例代码:
C++:

Mat ReadImage=imread("E:/TestImage/test1.bmp",0);
Mat ReadImage_1=imread("E:/TestImage/test2.bmp",0);
Mat AddImage=ReadImage+ReadImage_1;
Mat SubImage=ReadImage-ReadImage_1;
Mat MulImage=ReadImage*2;
Mat DivImage=ReadImage/1.2;

Python:

#如果支持中文路径,可以采用以下方式
#ReadImage=cv2.imread("E:/TestImage/test1.bmp",0)
#如果不支持中文,请采用以下方式
ReadImage = cv2.imdecode(np.fromfile("E:/TestImage/test1.bmp", dtype =np.uint8),0)
#如果支持中文路径,可以采用以下方式
#ReadImage_1=cv2.imread("E:/TestImage/test2.bmp",0)
#如果不支持中文,请采用以下方式
ReadImage_1 = cv2.imdecode(np.fromfile("E:/TestImage/test2.bmp", dtype =np.uint8),0)
AddImage=ReadImage+ReadImage_1
SubImage=ReadImage-ReadImage_1
MulImage=ReadImage*2
DivImage=ReadImage/1.2

EmguCV:

Mat ReadImage=CvInvoke.Imread("E:/TestImage/test1.bmp",(ImreadModes)0);
Mat ReadImage_1=CvInvoke.Imread("E:/TestImage/test2.bmp",(ImreadModes)0);
Mat AddImage=ReadImage+ReadImage_1;
Mat SubImage=ReadImage-ReadImage_1;
Mat MulImage=ReadImage*2;
Mat DivImage=ReadImage/1.2;

OpenCVSharp:

Mat ReadImage= Cv2.ImRead("E:/TestImage/test1.bmp",(ImreadModes)0);
Mat ReadImage_1= Cv2.ImRead("E:/TestImage/test2.bmp",(ImreadModes)0);
Mat AddImage=ReadImage+ReadImage_1;
Mat SubImage=ReadImage-ReadImage_1;
Mat MulImage=ReadImage*2;
Mat DivImage=ReadImage/1.2;

结果图像如下:
原图1
原图2
加
减
乘
除

五、总结

以上是一些常见的创建 Mat 数据的方法和技巧以及Mat数据的加减乘除操作。当然,还有其他一些创建Mat的方法,使用这些方法,可以根据需要创建不同类型和大小的图像或矩阵,并进行进一步的图像处理或矩阵操作。熟练掌握OpenCV中的Mat创建方法以及加减乘除操作,对于后面熟悉OpenCV的使用是非常有用处的。
OpenCV数字图像处理学习平台是一个交互式可视化操作平台,直接鼠标操作即可快速掌握OpenCV的使用。该学习帮平台可以根据操作过程自动生成代码,直接复制到自己的程序里面就可以使用,生产的代码包括c++、python、OpenCVsharp、emgucv四种语言。助文档有每个函数的完整示例代码。
OpenCV数字图像处理学习平台下载地址:
链接: https://pan.baidu.com/s/1XyotEmXLfD-XCNCYOiVUYg
提取码: aj9d

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

系统学习OpenCV

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值