Chapter 04 图像和大数组类型
主要介绍两大数据结构: cv::Mat
、 cv::SparseMat
。
cv::Mat n维稠密数组
稠密是指每一个指定的位置,都有具体的数据值对应,即使矩阵中有很多相同的值。
内存填充,是为了提高访问效率。
Mat 中元素的类型定义:数据类型 + 通道数,CV_{8U,16S,16U,32S,32F,64F}C{1,2,3}
。创建多于3通道的类型时,使用函数 CV_{8U,16S,16U,32S,32F,64F}C(int channels)
。
cv::Mat m;
m.create(3, 10, CV_32FC3);
m.setTo(cv::Scalar(1.0f, 0.0f, 1.0f));
// 等效于
cv::Mat m(3, 10, CV_32FC3, cv::Scalar(1.0f, 0.0f, 1.0f));
构造函数
function | 描述 |
---|---|
cv::Mat; | 默认 |
cv::Mat(int rows, int cols, int type); | 二维 |
cv::Mat(int rows, int cols, int type, const Scalar& s); | 有初始值的二维 |
cv::Mat(int rows, int cols, int type, void* data, size_t step=AUTO_STEP); | 以之前存在的值初始化二维数组 |
cv::Mat(cv::Size sz, int type); | 二维(size) |
cv::Mat(cv::Size sz, int type, const Scalar& s); | 二维有初始值 |
cv::Mat(cv::Size sz, int type, void* data, size_t step=AUTO_SIZE); | 已存在的数据初始二维数组 |
cv::Mat(int ndims, const int* sizes, int type); | 指定类型的多维数组 |
cv::Mat(int ndims, const int* sizes, int type, const Scalar& s); | 有初始值的多维类型 |
cv::Mat(int ndims, const int* sizes, int type, void* data, size_t step=AUTO_SIZE); | 已存在数据初始化多维数组 |
size_t : 无符号整型,其占用内存大小由编译类型决定,32位编译4字节,64位编译则8字节。使用size_t可能会提高代码的可移植性、有效性或者可读性。
复制构造函数
函数 | 描述 |
---|---|
cv::Mat(const Mat& mat) | 复制构造函数 |
cv::Mat(const Mat& mat, const cv::Range& rows, const cv::Range& cols); | 复制子行和列 |
cv::Mat(const Mat& mat, const cv::Rect& roi); | 复制子区间 |
cv::Mat(const Mat& mat, const cv::Range* ranges); | n维复制交叉部分 |
cv::Mat(const cv::MatExpr& expr); |
模板构造函数
创建和模板相同维度,相同类型的数组。
函数 | 说明 |
---|---|
cv::Mat(const cv::Vec<T,n>& vec, bool copyData=true); | 1维 |
cv::Mat(const cv::Matx<T,m,n>& vec, bool copyData=true); | 二维 |
cv::Mat(const std::vector& vec, bool copyData=true); | 1维 |
静态函数
创建二维数组
cv::Mat::zeros(rows cols, type) 、cv::Mat::ones(rows, cols, type) 、 cv::Mat::eye(rows, cols, type)
访问元素
-
at()
-
指针访问 ptr<>
-
迭代器访问: cv::MatIterator<> 、 cv::MatConstIterator<> ,m.begin() 、 m.end()
在用迭代器访问具体元素时,被拉伸为一维,需要手动计算位置。
N-ary 数组迭代器:对整个mat进行迭代,example4_1.cpp 。
访问元素块
函数 | 说明 |
---|---|
m.row(i); | m的第i行数组 |
m.col(j); | m的第j列数组 |
m.rowRange(i0, i1); | m的第i0行到第i1-1行 |
m.rowRange(cv::Range(i0, i1)); | |
m.colRange(j0, j1); | m的第j0列到第j1-1列 |
m.colRange(cv::Range(j0, j1)); | |
m.diag(d); | d个偏移的对角线数组 |
m(cv::Range(i0, i1), cv::Range(j0, j1)); | 行列范围同时选取 |
m(cv::Rect(i0, i1, w, h)); | 二维范围选取 |
m(ranges); | 多维数组的选取 |
Mat可用的代数表达式
- m0 + m1, m0 - m1 : 矩阵的加减运算
- m0 + s, m0 - s, s + m0, s - m0, -m0 : 矩阵和数字的加减运算
- s * m0, m0 * s : 矩阵和数字的乘法
- m0.mul(m1), m0/m1 : 矩阵的每个元素之间的乘除
- m0 * m1 : 矩阵乘法
- m0.inv(method) : 逆矩阵, method = DECOMP_LU, DECOMP_CHOLESKY, DECOMP_SVD
- m0.t() : 转置矩阵
- m0 > m1等逻辑运算,表示每个元素之间的比较,返回uchar类型矩阵
- m0 & m1; m0 | m1; s & m0等按位逻辑运算
- min(m0, m1), min(s, m0), min(m0, s) 等每个元素的最大,最小
- cv::abs(m0)
- m0.cross(m1), m0.dot(m1)
cv::SparseMat
使用哈希表存储非0元素
大数据类型的模板结构
cv::Mat_<>
和 cv::SparseMat_<>
两个模板;
模板能保证参数的统一,如:
// 不会检查 sm 的元素类型
void printMat(const cv::SparseMat* sm);
// 会在编译时对 sm 的元素类型进行检查
void printMat(const cv::SparseMat_<float>* sm);