OpenCV学习(3): Mat 类使用

Mat 类使用


构造

基本参数

Mat对象的构造主要需要提供一些参数,当然其中有些参数是默认的,用户可以不提供。这些参数主要包括对象的通道数,尺寸,数据,步长等,其中数据单独存放,其他统称为头部(Header).
- 矩阵尺寸给出的是矩阵的大小(行列数),通常的方式有枚举形式([rows,cols])、向量形式(vector& size)、数组指针(int * size);
- 类型就是之前定义的Array Type;
- 矩阵数据值通常是一个指向矩阵的指针(int* data);
- 步长也通常是一个数组指针(size_t * step)。

type变量

在构造函数中,通常可以看到需要输入一个整型的变量type,这个参数是通过宏定义在相关头文件中定义过的。用来指明Mat对象的存储的数据类型(主要是data部分)。其各部分含义可以如下:
CV_[位数][带符号与否][类型前缀]C[通道数]:CV_8UC1表示8位的单通道无符号char型数组, CV_32FC2表示一个2通道的23位浮点型数组。
(depth:深度)
CV_8U: bool或者uchar
CV_8S: schar或者char
CV_16U: ushort
CV_16S: short
CV_32S: int或者unsigned
CV_32F: float
CV_64F: double

//部分宏定义
#define CV_8UC1 CV_MAKETYPE(CV_8U,1)
#define CV_8UC2 CV_MAKETYPE(CV_8U,2)
#define CV_8UC3 CV_MAKETYPE(CV_8U,3)
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))

//构造函数
Mat();
Mat(int rows, int cols, int type);

type变量是整型,这也就是说如果知道了宏定义对应的整型值则可以直接输入。如下列两个语句是等价的。

Mat matrix(3, 3, CV_8UC1);
Mat matrix(3, 3, 0);

opencv中Mat存在各种类型,其中mat有一个type()的函数可以返回该Mat的类型。类型表示了矩阵中元素的类型以及矩阵的通道个数,它是一系列的预定义的常量,其命名规则为CV_(位数)+(数据类型)+(通道数)。具体的有以下值:
type

Scalar类型

Scalar类型定义的是一个四维的向量,可以和类型CvScalar互相转换。使用Scalar对象可以为Mat对象的每个通道赋值,默认值为0。通常使用三通道就可以表示一幅RGB图像。

class cv::Scalar_< _Tp >;//一个从`类Vec`派生过来的四维向量
typedef Scalar_<double> cv::Scalar;
//构造函数
Mat(int rows, int cols, int type, const Scalar& s);
Mat matrix(3, 3, CV_8UC1,Scalar(0));//为每个通道的对应元素都赋初值0

Size类型

Size(尺寸)类的数据成员是width和 height。注意在Size 中 width是我们通常意义上图像的列数(cols),而 height则对应着图像的行数(rows)。也就是说两者是相反的,这在初始化的时候需要注意。

typedef Size_<int> Size2i;  
typedef Size2i Size;  
typedef Size_<float> Size2f;  
//构造函数
Mat(Size size, int type, const Scalar& s);

维数与通道

维数指的是每个通道的维数,一般指一维或者二维;通道指的是每个元素具有几个值。可以理解为每个元素其实又是一个多维数组,但这个数组的维度最大为4(与scalar类型的定义相同)。当指明维数参数ndims时,通常搭配 指明尺寸的数组或者向量使用:

 Mat(int ndims, const int* sizes, int type, const Scalar& s);
 Mat(const std::vector<int>& sizes, int type, const Scalar& s);
 Mat(int ndims, const int* sizes, int type);
 //代码例子:
 int sizes[] = { 3,3 };
 Mat matrix(2, sizes, CV_64FC1, Scalar(1));//二维 3*3 单通道矩阵
 Mat matrix_(1, sizes, CV_64FC1,Scalar(1)); // 一维 3*1 单通道矩阵,虽然sizes是二维

Range类型

用来指明一个序列的连续子序列。拥有两个公共成员:start 和 end。可以使用这两个成员来表示子序列的范围,左开右闭。可以使用Range.all()表示所有。

Range ();
Range (int _start, int _end);
//构造函数
Mat(const Mat& m, const Range& rowRange, const Range& colRange=Range::all());

Rect类型

创建一个矩形区域,可以用来提取兴趣区域。前两位为一个坐标,后两位表示偏移量。

Mat(const Mat& m, const Rect& roi);

其他类型转化为矩阵

向量、列表、数组、二维点,三维点均可以显式地转换为矩阵,注意并不会隐式地转化。

template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false);
template<typename _Tp, typename = typename std::enable_if<std::is_arithmetic<_Tp>::value>::type>
    explicit Mat(const std::initializer_list<_Tp> list);
template<typename _Tp> explicit Mat(const std::initializer_list<int> sizes, const               std::initializer_list<_Tp> list);
template<typename _Tp, size_t _Nm> explicit Mat(const std::array<_Tp, _Nm>& arr, bool copyData=false);
template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true);
template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true);

运算

加、减、乘

矩阵重载了很多基本的数学运算符: A+B,AB,AB A + B , A − B , A ∗ B 注意:其中矩阵相乘时,两个矩阵的类型要相同,且需要depth为浮点型,即CV_32F或者CV_64F。

赋值

1。从基本的矩阵赋值方式如下,此种方式不会重新分配内存,只是复制头部并增加引用计数。

Mat& operator = (const Mat& m);
void assignTo( Mat& m, int type=-1 ) const;

2。从矩阵表达式赋值,如果左边的矩阵有着需求的尺寸,则重新利用;否则重新分配。

Mat& operator = (const MatExpr& expr);

3。 将矩阵的元素都设置为某一个标量。

 Mat& operator = (const Scalar& s);
 Mat& setTo(InputArray value, InputArray mask=noArray());

点乘、叉乘

点乘是将矩阵变成一个向量,两个向量做点积运算,最后的结果是一个实数。

Mat cross(InputArray m) const;
double dot(InputArray m) const;

element-wise 乘、除

对应元素作乘除法。

MatExpr mul(InputArray m, double scale=1) const;

特殊矩阵

0矩阵

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);

全1矩阵

static MatExpr ones(int rows, int cols, int type);
static MatExpr ones(Size size, int type);
static MatExpr ones(int ndims, const int* sz, int type);

单位矩阵

static MatExpr eye(int rows, int cols, int type);
static MatExpr eye(Size size, int type);

对角矩阵

static Mat diag(const Mat& d);
Mat diag(int d=0) const;

拷贝

clone()会将矩阵的所有信息(包括头部和数据部分)都拷贝到目标矩阵中,也就是说并不会共享数据。
coyTo()会将矩阵的数据部分拷贝到目的矩阵,且在拷贝之前会调用creat()函数。

Mat clone() const;
void copyTo( OutputArray m ) const;
void copyTo( OutputArray m, InputArray mask) const;

特殊操作

变形

    Mat reshape(int cn, int rows=0) const;
    Mat reshape(int cn, int newndims, const int* newsz) const;
    Mat reshape(int cn, const std::vector<int>& newshape) const;

转置

MatExpr t() const;

求逆

 MatExpr inv(int method=DECOMP_LU) const;

添加元素
在矩阵的末尾添加元素

void push_back_(const void* elem);
template<typename _Tp> void push_back(const _Tp& elem);
template<typename _Tp> void push_back(const Mat_<_Tp>& elem);
template<typename _Tp> void push_back(const std::vector<_Tp>& elem);
void push_back(const Mat& m);
void pop_back(size_t nelems=1);

类型转换

将矩阵中的元素数据类型转换为所需的类型。但这只是在矩阵内部转化,返回的是 void。 如果需要从数组、向量或列表等形式转化为矩阵,需要显示的使用构造函数。注意,这个函数改变的数据的depth而不会改变channels。其计算方式为: m(i,j)=m(i,j)α+β m ( i , j ) = m ( i , j ) ∗ α + β 在对图像的矩阵进行转换时,有时候需要设置其余两个参数,否则在使用imshow函数的时候可能会造成显示错误。如:灰度值范围在0~255,其在浮点数范围内是0~1,如果图像数据转换为浮点型而没有进行缩放则会将大于1的的值在显示的时候都是白色。

 void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;

ROI提取

void locateROI( Size& wholeSize, Point& ofs ) const;
Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );
Mat operator()( Range rowRange, Range colRange ) const;
Mat operator()( const Rect& roi ) const;
Mat operator()( const Range* ranges ) const;
Mat operator()(const std::vector<Range>& ranges) const;
template<typename _Tp> operator std::vector<_Tp>() const;
template<typename _Tp, int n> operator Vec<_Tp, n>() const;
template<typename _Tp, int m, int n> operator Matx<_Tp, m, n>() const;

元素访问

在使用at方法来访问矩阵的元素时,需要注意的是元素的类型(Typename),一旦两者不匹配(depth不同),则会造成访问错误。通常有:
CV_8U: bool或者uchar
CV_8S: schar或者char
CV_16U: ushort
CV_16S: short
CV_32S: int或者unsigned
CV_32F: float
CV_64F: double

template<typename _Tp> _Tp& at(int i0=0);
template<typename _Tp> const _Tp& at(int i0=0) const;
template<typename _Tp> _Tp& at(int row, int col);
template<typename _Tp> const _Tp& at(int row, int col) const;
template<typename _Tp> _Tp& at(int i0, int i1, int i2);
template<typename _Tp> const _Tp& at(int i0, int i1, int i2) const;
template<typename _Tp> _Tp& at(const int* idx);
template<typename _Tp> const _Tp& at(const int* idx) const;
template<typename _Tp, int n> _Tp& at(const Vec<int, n>& idx);
template<typename _Tp, int n> const _Tp& at(const Vec<int, n>& idx) const;
template<typename _Tp> _Tp& at(Point pt);
template<typename _Tp> const _Tp& at(Point pt) const;

迭代器

template<typename _Tp> MatIterator_<_Tp> begin();
template<typename _Tp> MatConstIterator_<_Tp> begin() const;
template<typename _Tp> MatIterator_<_Tp> end();
template<typename _Tp> MatConstIterator_<_Tp> end() const;

template<typename _Tp, typename Functor> void forEach(const Functor& operation);
template<typename _Tp, typename Functor> void forEach(const Functor& operation) const;

返回指针的函数

行指针

const uchar* ptr(int i0=0) const;\\指针为什么是uchar??
uchar* ptr(int i0=0);
uchar* ptr(int row, int col);
const uchar* ptr(int row, int col) const;

uchar* ptr(int i0, int i1, int i2);
const uchar* ptr(int i0, int i1, int i2) const;

const uchar* ptr(const int* idx) const;
template<int n> uchar* ptr(const Vec<int, n>& idx);
template<int n> const uchar* ptr(const Vec<int, n>& idx) const;
template<typename _Tp> _Tp* ptr(int i0=0);
template<typename _Tp> const _Tp* ptr(int i0=0) const;
template<typename _Tp> _Tp* ptr(int row, int col);
template<typename _Tp> const _Tp* ptr(int row, int col) const;
template<typename _Tp> _Tp* ptr(int i0, int i1, int i2);
template<typename _Tp> const _Tp* ptr(int i0, int i1, int i2) const;
template<typename _Tp> _Tp* ptr(const int* idx);
template<typename _Tp> const _Tp* ptr(const int* idx) const;
template<typename _Tp, int n> _Tp* ptr(const Vec<int, n>& idx);
template<typename _Tp, int n> const _Tp* ptr(const Vec<int, n>& idx) const;

内存管理

void create(int rows, int cols, int type);
void create(Size size, int type);
void create(int ndims, const int* sizes, int type);
void create(const std::vector<int>& sizes, int type);

void release();
void deallocate();
void copySize(const Mat& m);
void reserve(size_t sz);
void reserveBuffer(size_t sz);
void resize(size_t sz);
void resize(size_t sz, const Scalar& s);

size_t elemSize() const;//查看元素字节大小.
size_t elemSize1() const;//查询每个元素通道的字节大小.
int type() const;//查询元素的类型.

其他函数


bool isContinuous() const;
bool isSubmatrix() //! 查看矩阵是否是子矩阵
void addref();//增加引用计数
int depth() const;\\查询矩阵元素的深度.enum{CV_8U=0,CV_8S=1,CV_16U=2,CV_16S=3,CV_32S=4,CV_32F=5,CV_64F=6}        
int channels() const;\\查询通道数
size_t step1(int i=0) const;\\查看标准化步长.
bool empty() const;\\查询是否空矩阵.
size_t total() const;\\查询元素的个数.
size_t total(int startDim, int endDim=INT_MAX) const;\\查询指定区域的元素数目.
int checkVector(int elemChannels, int depth=-1, bool requireContinuous=true) const;\\?

公共变量

int flags 含有多个位域的标志:
- the magic signature\\??
- 连续标志
- 深度
- 通道数

int dims 矩阵维度, >= 2

int rows, cols 当矩阵有多个维度时,行数及列数或者(-1, -1)

uchar* data 指向数据的指针

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值