純小白記錄下騰訊的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的方法。