opencv类简单分析: Mat

Posted arvik

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了opencv类简单分析: Mat相关的知识,希望对你有一定的参考价值。

定义

class CV_EXPORTS Mat

    public:
    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<int>& sizes, int type);
Mat(int ndims, const int* sizes, int type, const Scalar& s);
Mat(const std::vector<int>& 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<int>& 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<Range>& ranges);

rows 定义二维数组的行
cols 定义二维数组的列
type 指明数组类型,使用CV_8UC1, …, CV_64FC4则创建一个1-4通道的矩阵,使用CV_8UC(n), …, CV_64FC(n)则创建多通道的矩阵,最多CV_CN_MAX 通道
size 指定二维数组大小,参看opencv的size类
s 指定像素值(标量),参看opencv的Scalar类
ndims 定义数组的维度
sizes 指定n维数组形状的整型数组,(就是一个整型数组的指针)
m 另一个矩阵类
data 用户数据指针
step 矩阵每行所占的字节数,包括填充(padding)字节数,默认为AUTO_STEP
steps 在多维数组中的ndims-1维数组(最后一步总是设置元素大小),如果未指定,则假定矩阵是连续的
rowRange 要取的m行的范围, 包含起始行,不包含结束行,使用Range::all()取所有行
colRange 要取的m列的范围, 包含起始列,不包含结束列,使用Range::all()取所有列
roi 感兴趣区域,参考opencv的Rect类
ranges 沿每个维度选择m范围的数组

    template<typename _Tp> explicit Mat(const std::vector<_Tp>& vec, bool copyData=false);
#ifdef CV_CXX11
    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);
#ifdef CV_CXX_STD_ARRAY
    template<typename _Tp, size_t _Nm> explicit Mat(const std::array<_Tp, _Nm>& arr, bool copyData=false);
#endif
    template<typename _Tp, int n> explicit Mat(const Vec<_Tp, n>& vec, bool copyData=true);
    template<typename _Tp, int m, int n> explicit Mat(const Matx<_Tp, m, n>& mtx, bool copyData=true);
    template<typename _Tp> explicit Mat(const Point_<_Tp>& pt, bool copyData=true);
    template<typename _Tp> explicit Mat(const Point3_<_Tp>& pt, bool copyData=true);
    template<typename _Tp> explicit Mat(const MatCommaInitializer_<_Tp>& commaInitializer);
    explicit Mat(const cuda::GpuMat& m);

成员变量

成员类型解释
flagsright-aligned标志,包含几个标志位(深度,通道数… )
dimsint矩阵的维数,>= 2
rows, colsint矩阵的维数, >= 2
datauchar*用户数据
datastart,dataend, datalimitconst uchar*辅助字段用于locateROI和adjustROI
allocatorMatAllocator*自定义分配器
uUMatData*与UMat互动
sizeMatSize
setp colsMatStep

成员函数

  • 将Mat类转换成UMat类
    UMat getUMat(int accessFlags, UMatUsageFlags usageFlags = USAGE_DEFAULT) const;

  • 取出指定区域

Mat rowRange(int startrow, int endrow) const;
Mat rowRange(const Range& r) const;
Mat colRange(int startcol, int endcol) const;
Mat colRange(const Range& r) const;
  • 提取对角线
Mat diag(int d=0) const;
static Mat diag(const Mat& d);

example:
Mat m = (Mat_<int>(3,3) << 
                1,2,3
                4,5,6
                7,8,9 )
Mat d0 = m.diag(0);
Mat d1 = m.diag(1);
Mat d_1 = m.diag(-1);

the result matrices are:
     d0 =
       [1;
        5;
        9]
     d1 =
       [2;
        6]
     d_1 =
       [4;
        8]
  • 克隆
    Mat是分头部信息和数据区的,一般的赋值只是新生成一个头部区域,共享数据区。这里的clone()创建数组和基础数据的完整副本(头部 + 数据)
Mat clone() const;
  • 复制矩阵
    m为目标矩阵,如果复制前矩阵大小不合适,则会重新分配内存
    mask 掩膜,备操作图像需要被掩盖的位置的点可以用掩膜来实现

    注意:
    对于三通道彩色图像,某个通道中所有在掩膜中值为0的点在该通道上的像素值变为0,其他所有非0值保持和原来不变。例如当对红色和蓝色通道加掩膜时会呈现一种图像被盖了一层绿色的效果。(因为蓝色和红色被掩盖了) 不管是灰度图像还是彩色图像,只有掩膜中像素值为0的点会对图像产生掩盖效果
    掩膜的depth和要被操作的图像的depth是一样的,rgb掩膜中也有三个通道,掩膜每个通道中对应位置值为0的点覆盖掉被操作图像中对应通道中的对应点,掩膜各个通道中非零值的点对原图像不产生任何影响

void copyTo( OutputArray m ) const;
void copyTo( OutputArray m, InputArray mask ) const;
  • 矩阵变换
    m 变换后的矩阵
    rtype 目标矩阵的类型。因为目标矩阵的通道数与源矩阵一样,所以rtype也可以看做是目标矩阵的位深度。如果rtype为负值,目标矩阵和源矩阵将使用同样的类型
    alpha 尺度变换因子(可选)
    beta 附加到尺度变换后的值上的偏移量(可选)
    计算方法 m(x,y)=saturate_cast<rtype>(αx(this)(x,y)+β)  m ( x , y ) = s a t u r a t e _ c a s t < r t y p e > ( α x ( ∗ t h i s ) ( x , y ) + β ) ,简单点就是一个 y=αx+β  y = α x + β 的一个线性转换
void convertTo( OutputArray m, int rtype, double alpha=1, double beta=0 ) const;
例子
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/core/core.hpp>
#include <iostream>

using namespace cv;
using namespace std;
int main()
    cv::Mat image = cv::imread("test1.jpg");
    cv::Mat dst;
    image.convertTo(dst, -1, 0.8, 80);
    cv::imshow("src", image);
    cv::imshow("result", dst);

    cv::waitKey();
    return 0;

  • 矩阵变换2
    如果参数type小于0,则该函数直接将 *this赋值给参数m,否则相当于convertTo(m, type)
void assignTo( Mat& m, int type=-1 ) const;
  • 赋值
    所有或部分数组元素设置为指定的值
Mat& operator = (const Scalar& s);
  • 设置
    operator =的高级变体
Mat& setTo(InputArray value, InputArray mask=noArray());
  • 变形
    在不复制数据的情况下更改二维矩阵的形状和/或通道数。
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;
例子:
Mat data = Mat(20, 30, CV_32F);  // 20行,30列,1通道    600大小Mat dst = data.reshape(0, 1);  则dst形状: 1通道不变,1行, 600列Mat dst = data.reshape(0, data.rows*data.cols);  则dst形状: 1通道不变,600行, 1列Mat dst = data.reshape(2, 0);  则dst形状: 2通道, 20行不变, 15列Mat dst = data.reshape(2, data.rows/5);  则dst形状: 2通道, 4行, 75列
  • 转置矩阵
    该方法求当前矩阵的转置矩阵,当前矩阵的实际数据不变,返回一个临时矩阵,注意返回值类型是MatExpr
    求转置矩阵的方法参考高等数学
MatExpr t() const;
  • 逆矩阵

method 求逆方法,例如:cv::DecompTypes ,默认DECOMP_LU

MatExpr inv(int method=DECOMP_LU) const;
  • 矩阵相乘
    m 和当前矩阵形状相同的矩阵
    scale 比例因子

    该函数并不等同于高等数学上的矩阵乘法运算。该函数仅仅只是两个矩阵对应位置相乘

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

example:
A = [ 60,2,3;
      4,5,6;
      7,8,9]

B = [ 60,2,3;
      4,5,6;
      7,8,9]

AB = A.mul(B)
[A11 * B11, A12 * B12, A13 * B13;
A21 * B21, A22 * B22, A23 * B23;
A31 * B31, A32 * B32, A33 * B33;
]

则
AB的值 = [255, 4, 9;
        16, 25, 36;
        49, 64, 81]
  • 两个3元向量的叉积
    很少使用
Mat cross(InputArray m) const;
  • 计算两个向量的点积
    相当于运用mul方法后再对每个元素求和,最终返回值是一个double类型的值
    个人感觉该函数没什么作用或者意义
    对于两个矩阵A,B,则dot的计算公式 v= m,n i=1,j=1 A ij B ij =A 11 B 11 +A 12 B 12 +....A mn B mn   v = ∑ i = 1 , j = 1 m , n A i j ∗ B i j = A 11 ∗ B 11 + A 12 ∗ B 12 + . . . . A m n ∗ B m n
double dot(InputArray m) const;
  • 零矩阵、1矩阵、单位矩阵、新建矩阵
    返回指定大小和类型的数组
    rows,cols 矩阵的行列
    type 形状
    size 指定大小
    ndims 维度
    sz 指定数组形状的整数数组(就是一个整型数组的指针)
    sizes 指定数组形状的vector(就是一个vector对象)
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);

static MatExpr ones(int rows, int cols, int type);
static MatExpr ones(int rows, int cols, 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);

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 addref(); //加 1 引用计数
void release(); //减 1 引用计数,必要时释放矩阵
  • 矩阵重分配
    内部使用功能,考虑改用release方法。重新分配矩阵的数据
void deallocate();
  • 大小复制
    内部使用功能
void copySize(const Mat& m);
  • 预留空间
void reserve(size_t sz); //为一定数量的行预留空间
void reserveBuffer(size_t sz);//为特定字节数保留空间
  • 大小重设
    sz 新矩阵的行数
void resize(size_t sz);//改变矩阵行数
void resize(size_t sz, const Scalar& s);//
  • 追加/去除数据
    内部使用
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 locateROI( Size& wholeSize, Point& ofs ) const;

  • 部分函数
void locateROI( Size& wholeSize, Point& ofs ) const;
Mat& adjustROI( int dtop, int dbottom, int dleft, int dright );

bool isContinuous() const; // 判断是否连续
bool isSubmatrix() const;//判断该矩阵是否是子矩阵
size_t elemSize() const; //返回像素所占字节大小
size_t elemSize1() const; //返回channel的大小
int type() const; //返回图像矩阵类型,如三通道 CV_16SC3
int depth() const; //返回矩阵元素深度,如CV_8U(8-bit unsigned integers ( 0..255 ))、CV_8S、CV_32S
int channels() const; //返回矩阵通道数
size_t step1(int i=0) const;//该方法返回一个矩阵步骤,该步骤除以Mat::elemSize1().快速访问任意矩阵元素可能很有用。
bool empty() const;//判空,检测矩阵是否没有任何元素
size_t total() const; //返回元素总个数
size_t total(int startDim, int endDim=INT_MAX) const;
  • 元素指针
uchar* ptr(int i0=0);  //指向第i0维首个位置元素
const uchar* ptr(int i0=0) const;
uchar* ptr(int row, int col); //指向第row行第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; //指向第i0,i1,i2维度指定数据
uchar* ptr(const int* idx); //指向位置索引处
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;
  • 元素数组访问
 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;

运算符重载

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;

Mat(Mat&& m);
Mat& operator = (Mat&& m);

以上是关于opencv类简单分析: Mat的主要内容,如果未能解决你的问题,请参考以下文章

OpenCV Mat类常用成员属性和成员方法

OpenCV Mat类常用成员属性和成员方法

标量的OpenCV双矩阵除法产生不正确的结果

opencv常用api简单分析: imread()

opencv源代码分析:icvGetTrainingDataCallback简单介绍

OpenCV学习:Mat结构中的数据共享机制