纯小白记录下腾讯的ncnn框架源码的学习。纯粹写给自己看的,不保证正确性。
Mat 类似于 caffe中的blob,是一个张量的存储结构体。
一、数据成员:
1、void * data 多维数据按一位数组来存储。并且需要是16字节对齐的。
2、int * refcount *refcount表示这个Mat被引用的个数。类似于智能指针?×refcount == 0 自动释放。
3、size_t elemsize 每个元素的大小。sizeof(type)
4、dims 维度。如果是1维就是向量只有w,2维就是平面w * h, 3维就是立方体 w * h * c。
5、w h c三个维度
6、cstep : channel step 每个channel 有多少个元素。注意是元素个数,而不是字节数。
total() = cstep * c 整个Mat有多少个元素。
二、方法成员:
void create(int _w, size_t _elemsize);
一维数组初始化。只有一个w。二维平面就是w h。
三维有些特殊:
cstep 不是单纯的 w * h, 而是要求每个channel的起始地址都是16字节对齐的。
cstep 是 w*h*elemsize在16的基础上,对齐得到的。
也就是说,cstep * elemsize 必须是16的倍数。
所以,三维mat的大小不是简单的elemsize* align(w * h * c,16)。而是elemsize* c* align(w*h, 16).
Mat Mat::channel(int c)
返回某一个channel的一维新Mat。
在channel内部,数据是连续的。channel之间可能有空隙。为了保证每个channel的起始地址是16对齐。
float * Mat::row(int y)
返回某一个Mat的第一个channel的第y个行的首地址。
template <typename T>
inline Mat::operator T*()
{
return (T*)data;
}
这个符号重载,神奇。把Mat转换成任意T *类型的指针。
返回的其内存地址。
inline float& Mat::operator[](int i)
{
return ((float*)data)[i];
}
重载了取下标操作,直接取其地址的第i个。
因为channel之间不是连续的,所以这么取对第1个以后的channel来说,可能会出问题。应该是对dim < 3的方法。