OpenCV2: Mat属性type,depth,step
Mat的常見屬性
- data? uchar型的指針。Mat類分為了兩個部分:矩陣頭和指向矩陣數據部分的指針,data就是指向矩陣數據的指針。
- dims 矩陣的維度,例如5*6矩陣是二維矩陣,則dims=2,三維矩陣dims=3.
- rows? 矩陣的行數
- cols?? 矩陣的列數
- size 矩陣的大小,size(cols,rows),如果矩陣的維數大于2,則是size(-1,-1)
- channels 矩陣元素擁有的通道數,例如常見的彩色圖像,每一個像素由RGB三部分組成,則channels = 3
下面的幾個屬性是和Mat中元素的數據類型相關的。
- type
表示了矩陣中元素的類型以及矩陣的通道個數,它是一系列的預定義的常量,其命名規則為CV_(位數)+(數據類型)+(通道數)。具體的有以下值:
這里U(unsigned integer)表示的是無符號整數,S(signed integer)是有符號整數,F(float)是浮點數。CV_8UC1 CV_8UC2 CV_8UC3 CV_8UC4 CV_8SC1 CV_8SC2 CV_8SC3 CV_8SC4 CV_16UC1 CV_16UC2 CV_16UC3 CV_16UC4 CV_16SC1 CV_16SC2 CV_16SC3 CV_16SC4 CV_32SC1 CV_32SC2 CV_32SC3 CV_32SC4 CV_32FC1 CV_32FC2 CV_32FC3 CV_32FC4 CV_64FC1 CV_64FC2 CV_64FC3 CV_64FC4
例如:CV_16UC2,表示的是元素類型是一個16位的無符號整數,通道為2.
C1,C2,C3,C4則表示通道是1,2,3,4
type一般是在創建Mat對象時設定,如果要取得Mat的元素類型,則無需使用type,使用下面的depth - depth
矩陣中元素的一個通道的數據類型,這個值和type是相關的。例如 type為 CV_16SC2,一個2通道的16位的有符號整數。那么,depth則是CV_16S。depth也是一系列的預定義值,
將type的預定義值去掉通道信息就是depth值:
CV_8U CV_8S CV_16U CV_16S CV_32S CV_32F CV_64F - elemSize
矩陣一個元素占用的字節數,例如:type是CV_16SC3,那么elemSize = 3 * 16 / 8 = 6 bytes - elemSize1
矩陣元素一個通道占用的字節數,例如:type是CV_16CS3,那么elemSize1 = 16? / 8 = 2 bytes = elemSize / channels
下面是一個示例程序,具體說明Mat的各個屬性:
Mat img(3, 4, CV_16UC4, Scalar_<uchar>(1, 2, 3, 4));cout << img << endl;cout << "dims:" << img.dims << endl;cout << "rows:" << img.rows << endl;cout << "cols:" << img.cols << endl;cout << "channels:" << img.channels() << endl;cout << "type:" << img.type() << endl;cout << "depth:" << img.depth() << endl;cout << "elemSize:" << img.elemSize() << endl;cout << "elemSize1:" << img.elemSize1() << endl;首先創建了一個3*4的具有4個通道的矩陣,其元素類型是CV_16U。Scalar_是一個模板向量,用來初始化矩陣的每個像素,因為矩陣具有4個通道,Scalar_有四個值。其運行結果:
運行結果首先打印了Mat中的矩陣,接著是Mat的各個屬性。注意其type = 26,而depth = 2。這是由于上面所說的各種預定義類型
例如,CV_16UC4,CV_8U是一些預定義的常量。
step
Mat中的step是一個MStep的一個實例。其聲明如下:
struct CV_EXPORTS MStep{MStep();MStep(size_t s);const size_t& operator[](int i) const;size_t& operator[](int i);operator size_t() const;MStep& operator = (size_t s);size_t* p;size_t buf[2];protected:MStep& operator = (const MStep&);};從其聲明中可以看出,MStep和size_t有比較深的關系。用size_t作為參數的構造函數和重載的賦值運算符
MStep(size_t s); MStep& operator = (size_t s);向size_t的類型轉換以及重載的[ ]運算符返回size_t
const size_t& operator[](int i) const;size_t& operator[](int i);size_t的數組以及指針?
size_t* p;size_t buf[2];那么size_t又是什么呢,看代碼
typedef unsigned int size_t;size_t就是無符號整數。
再看一下MStep的構造函數,就可以知道其究竟保存的是什么了。
inline Mat::MStep::MStep(size_t s) { p = buf; p[0] = s; p[1] = 0; }從MStep的定義可以知道,buff是一個size_t[2],而p是size_t *,也就是可以把MStep看做一個size_t[2]。那么step中保存的這個size_t[2]和Mat中的數據有何種關系呢。
step[0]是矩陣中一行元素的字節數。
step[1]是矩陣中一個元素的自己數,也就是和上面所說的elemSize相等。
上面說到,Mat中一個uchar* data指向矩陣數據的首地址,而現在又知道了每一行和每一個元素的數據大小,就可以快速的訪問Mat中的任意元素了。下面公式:
step1
規整化的step,值為step / elemSize1。 定義如下:
inline size_t Mat::step1(int i) const { return step.p[i]/elemSize1(); }仍以上例代碼中定義的img為例,來看下step,step1具體的值:
img(3*4)的type是CV_16UC4,step[0]是其一行所占的數據字節數4 *4 * 16 / 8? = 32.
step[1] 是一個元素所占的字節數,img的一個元素具有4個通道,故:4 * 16 / 8 = 2
step1 = step / elemSize1,elemSize1是元素的每個通道所占的字節數。
N維的step(N > 2)
上面分析step是一個size_t[2],實際不是很正確,正確的來說step應該是size_t[dims],dims是Mat的維度,所以對于上面的二維的Mat來說,step是size_t[2]也是正確的。
下面就對三維的Mat數據布局以及step(維度大于3的就算了吧)。
上圖引用自http://ggicci.blog.163.com/blog/static/210364096201261052543349/? 搜集資料時發現了這幅圖,一切就變的簡單了 ? 感謝作者 Ggicci
三維的數據在Mat中是按面來存儲的,上圖描述的很清晰,這里不再多說。
上面言道,step是一個size_t[dims],dims是維度。so,三維的step就是size_t[3]。其余的不多說了,看圖就有了。下面來創建一個三維的Mat,實際看看
首先創建一個3*3*3,depth為CV_16S的兩通道的Mat
step[0]是一個數據面的大小? 3 * 3 * (16 / 8 ) * 2 = 36
step[1]是一行數據的大小 3 * (16 / 8 ) * 2 = 12
step[2]是一個元素的大小 2 * (16 / 8) = 4
總結
以上是生活随笔為你收集整理的OpenCV2: Mat属性type,depth,step的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: filter2D函数
- 下一篇: 图像处理时一些卷积核子函数的生成