OpenCV-Mat結構詳解


前面博客中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;

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM