OPENCV的MAT类详解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
类Mat导言
OpenCV c + + n 维稠密数组类
类CV_EXPORTS Mat
{
public:
/ / … …很多的方法...
...
/*!包括几位字段:
-神奇的签名
-连续性标志
-深度(Note:应该是位深)
-通道数
*/
int flags;(Note :目前还不知道flags做什么用的)
//!数组的维数,> = 2
int dims ;
//!行和列的数量或(-1,-1) 此时数组已超过2 维
int rows,cols;
//!指向数据的指针
uchar *data ;
//!指针的引用计数器;
/ / 阵列指向用户分配的数据时,当指针为NULL
int * refcount ;
/ / 其他成员
...
};
Mat类表示一个n 维的密集数值单通道或多通道数组。它可以用于存储实数或复数值的向量和矩阵、灰度或彩色图像、体素、向量场、点云、张量、直方图(尽管较高维的直方图存储在SparseMat可能更好)。M 数组的数据布局是由阵列M.step[]定义的,使元素的地址(i0,。。。。i M.dims-1),其中0<= i k < M.size [k],可以计算为:
addr( Mi0 ;:::;i M.dims-1) = M.data+ M.step[ 0]*i0 + M.step[ 1] *i1+ .…+ M.step[ M:dims- 1]
i M:dims- 1
2维的数组的情况下根据上述公式被减至:
addr( M i,j)= M.data+ M.step[ 0]*i+ M.step[ 1] *j
请注意,M.step[i] > =M.step[i+1] (事实上,M.step[i] > =M.step[i+1]*M.size[i+1])。这意味着2维矩阵是按行存储的,3 维矩阵是由平面存储,以此类推。M.step[M.dims-1] 是最小的而且总是等于元素大小M.elemSize()。因此,Mat中的数据布局完全兼容OpenCV 1.x 中CvMat、IplImage、CvMatND类型。它也和标准工具包和SDK,如Numpy(ndarray),Win32(独立设备位图)等主流的密集数组类型相兼容,也就是说,与任何使用步进(或步长)来计算像素位置的阵列相兼容。由于这种兼容性,使用户分配的数据创建Mat头以及用OpenCV函数实时处理该头成为可能。有很多不同的方法,创建一个Mat的对象。下面列出了最常见的选项:
使用create(nrows,ncols,type)方法或类似的Mat(nrows,ncols,type [,fillValue])
构造函数。一个新的指定了大小和类型的数组被分配。type和cvCreateMat 方法中的type 参数具有相同的含义。例如,CV_8UC1 是指一个8 位单通道阵列,CV_32FC2 指 2 通道
(复)浮点阵列,以此类推。
//创建一个用1+3j填充的7 x 7 复矩阵。
Mat M(7,7,CV_32FC2,Scalar(1,3)) ;
/ /现在将M转换为100 x 60的CV_8UC(15)的矩阵。
/ / 旧内容将会被释放
M.create(100,60,CV_8UC(15)) ;
这一章导言中指出,当当前的数组与指定的数组的形状或类型create() 分配唯一的新数组时的形状或类型。
创建多维数组:
/ / 创建100 x 100 x 100 8 位数组
int sz[] = {100, 100, 100};
Mat. bigCube (3,sz,CV_8U,Scalar::all(0)) ;它将维度数(= 1)传递给Mat的构造函数,但列数设置为1时,创建数组将是2 维的。因此,Mat::dims 始终是>=2的(该数组为空时,也可以是0)。
使用的复制构造函数或赋值运算符可以是一个数组或右侧的表达式(请参阅
下图)。正像在导言中指出的,数组赋值运算复杂度是O(1)因为当你需要它的时候,它仅复制头和增加引用计数。Mat::clone() 方法可用于获取全(深)的副本数组。
为另一个数组的一部分构建头。它可以是单个行、单个列,几个行,几个列,矩形区域(代数中称为较小值)的数组或对角线。这种操作也是复杂度为O(1),因为,新头引用相同的数据。实际上,您可以使用此特性修改该数组的一部分例如:
/ /第5行,乘以3,加到第3 行,
M.row(3) = M.row(3) + M.row (5) * 3 ;
/ / 现在将第7列复制到第1列
/ / M.col(1) = M.col(7) ;/ / 这个不能实现。
Mat M1= M.col(1) ;
M.col(7).copyTo(M1) ;
/ / 创建一种新的320 x 240 图像
Mat img(Size(320,240),CV_8UC3) ;
/ / 选择ROI(region of interest)
Mat roi(img,Rect(10,10,100,100)) ;
/ / 填充(0,255,0)的ROI (这是RGB 空间中的绿色);
/ / 320 x 240 原始图像将被修改。
roi = Scalar(0,255,0) ;
由于额外的datastart 和dataend 的成员,它们使得用locateROI() 计算子数组在主容器数组中的相对的位置成为可能:
Mat A = Mat::eye ( 10, 10, CV_32S);
/ / 提取A 的1 (含)到3 (不包含)列。
Mat B = A(Range::all(),Range(1,3));
/ / 提取B 的5 (含)到9 (不包含)行。
/ /即C ~ A(Range(5,9),Range (1,3))
Mat C = B(Range(5,9),Range::all()) ;
Size size;Point ofs;
C.locateROI (size,ofs);
/ / size将变为(width= 10,height= 10),ofs会变为(x = 1,y = 5)
考虑到整个矩阵,如果您需要深层副本,使用子矩阵的sclone() 方法的提取。
为用户分配数据创建矩阵头。有利于执行下列操作:
1. 使用OpenCV处理"外来"的数据(例如,当您执行DirectShow *filter 或gstreamer的pro-cessing 模块,等等)。例如:
void process_video_frame (const unsignedchar * pixels,
int width,int height,int step)
{
Mat img (width,height, CV_8UC3,pixels,step);
GaussianBlur (img,img ,Size(7,7),1.5,1.5);
}
2.快速初始化小矩阵和/或获取超快的元素的访问。
double m[3] [3] = {{a,b,c},{d,e,f} {g, h, i}}};
Mat M = Mat(3,3,CV_64F,m).inv() ;