前面博客中Mat函數談到一些理解,但是理解的比較淺顯,下面談談通道,行列等意義;
Mat的常見屬性
opencv中type類型·
CV_<bit_depth>(S|U|F)C<number_of_channels>
1--bit_depth---比特數---代表8bite,16bites,32bites,64bites---舉個例子吧--比如說,
如果你現在創建了一個存儲--灰度圖片的Mat對象,這個圖像的大小為寬100,高100,那么,現在這張
灰度圖片中有10000個像素點,它每一個像素點在內存空間所占的空間大小是8bite,8位--所以它對應的就是CV_8
depth:深度,即每一個像素的位數(bits),在opencv的Mat.depth()中得到的是一個 0 – 6 的數字,分別代表不同的位數:enum { CV_8U=0, CV_8S=1, CV_16U=2, CV_16S=3, CV_32S=4, CV_32F=5, CV_64F=6 }; 可見 0和1都代表8位, 2和3都代表16位,4和5代表32位,6代表64位;
2--S|U|F--
S--代表---signed int---有符號整形
U--代表--unsigned int--無符號整形
F--代表--float---------單精度浮點型
3--C<number_of_channels>----代表---一張圖片的通道數,比如:
1--灰度圖片--grayImg---是--單通道圖像
2--RGB彩色圖像---------是--3通道圖像
3--帶Alph通道的RGB圖像--是--4通道圖像
如:CV_8UC1---則可以創建----8位無符號的單通道---灰度圖片------grayImg
CV_8UC3---則可以創建----8位無符號的三通道---RGB彩色圖像---colorImg
channels:通道,矩陣中的每一個矩陣元素擁有的值的個數,比如說 3 * 4 矩陣中一共 12 個元素,如果每個元素有三個值,那么就說這個矩陣是 3 通道的,即 channels = 3。常見的是一張彩色圖片有紅、綠、藍三個通道。
上面是一個 3 X 4 的矩陣,假設其數據類型為 CV_8U,也就是單通道的 uchar 類型
CV_8U 得到 M.depth() == 0, M.channels() == 1
這是一個二維矩陣,那么維度為 2 (M.dims == 2);
M.rows == 3; M.cols == 4;
step:是一個數組,定義了矩陣的布局,具體見上面圖片分析,另外注意 step1 (step / elemSize1),M.step[m-1] 總是等於 elemSize,M.step1(m-1)總是等於 channels;
因為是二維矩陣,那么 step 數組只有兩個值, step[0] 和 step[1] 分別代表一行的數據大小和一個元素的數據大小,則 M.step[0] == 4, M.step[1] == 1;
M.step1(0) == M.cols = 4; M.step1(1) == 1;
elemSize : 矩陣中每一個元素的數據大小,如果Mat中的數據的數據類型是 CV_8U 那么 elemSize = 1,CV_8UC3 那么 elemSize = 3,
CV_16UC2那么 elemSize = 4;
記住另外有個 elemSize1 表示的是矩陣中數據類型的大小,即 elemSize / channels 的大小
sizeof(uchar) = 1,那么每一個數據元素大小為 1 (M.elemSize() == 1, M.elemSize1() == 1);
CV_8U 得到 M.depth() == 0, M.channels() == 1;
假設上面的矩陣數據類型是 CV_8UC3,也就是三通道
M.dims == 2; M.channels() == 3;M.depth() == 0;
M.elemSize() == 3 (每一個元素包含3個uchar值) M.elemSize1() == 1 (elemSize / channels)
M.step[0] == M.cols * M.elemSize() == 12, M.step[1] == M.channels() * M.elemSize1() == M.elemSize() == 3;
M.step(0) == M.cols * M.channels() == 12 ; M.step(1) == M.channels() == 3;
上面博文參考:opencv數據結構-MAT結構詳解
寫到這里,我也只了解了行,列,通道等概念,但是step,step(0),elemSize1,elemSize()我感到很困惑,看看下面的理解:
上圖中: int matSize[] = {5,8,10};//每一維元素的個數:8:行,10:列
Mat mat1(3,matSize, CV_16UC3, Scalar::all(0);
對於mat1,3通道,一個像素點在內存空間大小是16bit;每一個像素的位數(bits)是2(深度);
三維矩陣,一共有三維,我們分別類比為
面:每個二維矩陣,表示第1維的元素
線:矩陣的每一行,表示第2維的元素
點:矩陣中每行的每個元素,表示第3維的元素
那么這樣子就可以解釋清楚每一維元素的含義了。
以step[i]為例
step[0]:面的大小,第1維的元素的大小,也就是二維矩陣的大小,一個二維矩陣有8行,所以step[0]=step[1]*8=480
step[1]:線的大小,第2維的元素的大小,也就是二維矩陣每一行的大小,由於每個元素大小為6,每行有10個元素,所以step[1]=10*6=60
step[2]:點的大小,第3維的元素的大小,這里矩陣的每個元素類型為CV_16UC3,所以step[2]=2*3=6個字節
這里注意:
1.step的大小是字節
2.注意下標與維數的對應關系:下標2對應點,1對應線,0對應面
3.矩陣有幾維,step[]數組就有幾個元素,如3維,則有3個元素,step[0],step[1],step[2].分別對應面,線,點
只要記住,最后一個總是表示點,然后依次向前為線,面…
4.第2,3 點 ,對於size和step1()也一樣。
step1(i):每一維元素的通道數
step[i]:每一維元素的大小,單位字節;(包含所有通道)
size[i]:每一維元素的個數
elemSize():每個元素大小,單位字節
elemSize1():每個通道大小,單位字節
elemSize 表示每個元素的大小(單位字節),每個元素可能有多個通道,示例中,每個元素有三個通道,而每個通道類型為CV_16U,算3個通道的總數, 2*3=6
elemSize1 每個通道的大小(單位字節),CV_16=2字節
step1[i] = step.p[i]/elemSize1();
step1[0] = step[0]/elemSize1 = 240 bytes
step1[1] = step[1]/elemSize1 = 30 bytes
step1[2] = step[2]/elemSize1 = 3 bytes
代碼如下:
#include"sift.h" #include<fstream> #include<iostream> #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #include <opencv2/core/core.hpp> #include <stdio.h> #include <stdlib.h> int main(int argc, char **argv) { //////////////////Demo1(3維矩陣)/////////////////////////////////////////// printf("//////////////////////Demo1(3維矩陣)////////////////////////\n"); //最后面的兩個數:(行,列),確定了一個面 //是一個依次降維的過程 //8,10組成了面,5個面,組成了立方體 int matSize[] = { 5,8,10 };//每一維元素的個數:8:行,10:列 Mat mat1(3, matSize, CV_16UC3, Scalar::all(0)); //求step[i]的大小:每一維元素的大小(單位字節) printf("\n///////step[i]的大小//////////\n"); printf("step[0]:%d\n", mat1.step[0]);//480=8*60:面的大小(第一維) printf("step[1]:%d\n", mat1.step[1]);//60=6*10:線的大小(第二維) printf("step[2]:%d\n", mat1.step[2]);//6=2*3:點的大小(第三維) //求size[i]:每一維元素的個數 printf("\n///////size[i]的大小///////\n"); printf("size[0]:%d\n", mat1.size[0]);//5:面 printf("size[1]:%d\n", mat1.size[1]);//8:線 printf("size[2]:%d\n", mat1.size[2]);//10:點 //求step1(i):每一維元素的通道數 printf("\n///////step1(i)的大小///////\n"); printf("step1(0):%d\n", mat1.step1(0));//240:面 printf("step1(1):%d\n", mat1.step1(1));//30:線 printf("step1(2):%d\n", mat1.step1(2));//3:點 //求elemSize:每個元素的大小(單位字節) printf("\n///////elemSize的大小///////\n"); printf("elemSize:%d\n", mat1.elemSize());//6:每個元素的大小 //求elemSize1:每個通道的大小(單位字節) printf("\n///////elemSize1的大小///////\n"); printf("elemSize1:%d\n", mat1.elemSize1());//2:每個通道的大小 system("pause"); return 0; }
改成.jpg圖片
/求step[i]的大小:每一維元素的大小(單位字節) //step[i] printf("\n///////step[i]的大小///////\n"); printf("step[0]:%d\n", mat2.step[0]);//1200=3*400:線 printf("step[1]:%d\n", mat2.step[1]);//3=1*3:點 //size[i] printf("\n///////size[i]的大小///////\n"); printf("size[0]:%d\n", mat2.size[0]);//250:線 printf("size[1]:%d\n", mat2.size[1]);//400:點 //step1(i) printf("\n///////step1(i)的大小///////\n"); printf("step1(0):%d\n", mat2.step1(0));//1200:第一維的通道數 printf("step1(1):%d\n", mat2.step1(1));//3:第二維的通道數 //elemSize printf("\n///////elemSize的大小///////\n"); printf("elemSize:%d\n", mat2.elemSize());//3:每個元素的大小 //elemSize1 printf("\n///////elemSize1的大小///////\n"); printf("elemSize1:%d\n", mat2.elemSize1());//1:每個通道的大小,也就是單通道數據類型 system("pause"); return 0;