Mat类的构造函数与析构函数太多了,真的太多了,这是可以理解的。矩阵是图像的基本数据结构,对于数字图像处理的人来说,矩阵是我们看待图像的一个重要角度,甚至是一个最主要的角度,因为,我们做的所有动作几乎都是在矩阵的基础之上完成的!矩阵是如此得基础,如此得任重道远,因此,矩阵类的实现自然不能怠慢。在具体应用上,有时我们直接声明一个矩阵了事,比如Mat img;有时,我们又需要详细地定义出矩阵的维度以及长、宽、数据类型等信息:Mat img(width,height,CV_8U);这就直接导致了Mat类一个庞大的构造函数群,如下所示:
Mat::Mat()
Mat::Mat(int rows, int cols, int type)
Mat::Mat(Size size, int type)
.....
Mat::Mat(int ndims, const int* sizes, int type, void* data, const size_t* steps=0)
Mat::Mat(const Mat& m, const Range* ranges)
浩浩荡荡,总共20个函数,一定不要怕这些函数,到构造函数的定义部分去看,其实这些函数基本都调用了下面create函数族群:
void create(int rows, int cols, int type);
void create(Size size, int type);
void create(int ndims, const int* sizes, int type);
举个例子,在构造函数Mat::Mat(int rows,int cols,int type)中:
inline Mat::Mat(Size _sz, int _type) : size(&rows)
{
initEmpty();
create( _sz.height, _sz.width, _type );
}
所以整个Mat构造函数的精髓部分就是create函数了,再深挖一层create函数,看一下create函数是怎么实现的,去掉create函数一些边界条件的小细节,核心部分如下:
void Mat::create(int d, const int* _sizes, int _type)//先行再列
{
if( !allocator )//如果当前矩阵没有内存配置器
{
//step.p[0]和size.p[0]是个值得说道的量,本Mat源码分析的下一篇博客会详细分析。
//refcount部分是引用计数,C++中一个重要技术,标志该段内存被引用的状况,很能体现这是C++的OpenCV
size_t totalsize = alignSize(step.p[0]*size.p[0], (int)sizeof(*refcount));(矩阵数据总空间大小,4字节对齐)
data = datastart = (uchar*)fastMalloc(totalsize + (int)sizeof(*refcount));
refcount = (int*)(data + totalsize);
*refcount = 1;
}
else //如果当前矩阵有内存配置器,直接使用内存配置器分配内存
{
allocator->allocate(dims, size, _type, refcount, datastart, data, step.p);
CV_Assert( step[dims-1] == (size_t)CV_ELEM_SIZE(flags) );
}
}
综上,Mat构造函数部分完成Mat结构中一些成员变量的初始化,以及内存的分配,是中规中矩的构造函数。
本部分有必要说下alignSize这个小函数,这个函数涉及到内存问题,说得具体点就是内存字节数量的问题。源码如下:
/*!
Aligns buffer size by the certain number of bytes
This small inline function aligns a buffer size by the certian number of bytes by enlarging it.
*/
static inline size_t alignSize(size_t sz, int n)
{
return (sz + n-1) & -n;
}
这种位操作函数是计算机中非常漂亮的函数,完美地利用了计算机中数据类型位数的有限性,源码注释中已经说明本函数功能是n字节对齐了,简要分析一下:alignSize中,-n就是负数啦,负数在用补码表示,负数的补码是其绝对值所有位按位取反加1,所以对于本例的n=4来说,-n的位模式是111......11100,最低两位是0,也就是能够达到4字节对齐的目的,所以(sz+n-1)&-n就能够达到了按照
4字节向上取整对齐的目的了。