![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5yMlBDNyMTY2UWOhFGMmFGOmdDN0MTYxM2M4EWZ4ITOz8CX0JXZ252bj91Ztl2Lc52YucWbp5GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.png)
前言
很多人不重視Mat的資料類型,其實,資料類型不對往往會導緻溢出、截斷等各種問題,使得計算結果看起來不對,讓人陷入迷茫。這篇文章我們來深入聊聊Mat的資料類型以及他們之間的轉換。
Mat有的資料類型
OpenCV的文檔中列出來的資料類型一共有30種,如下表對應。
但實際上,大于30的,比如CV_8UC5,這種是可以自己定義的。在程式的開頭用一句宏來定義即可。
#define CV_8UC4 CV_MAKETYPE(CV_8U,4)
#define CV_8UC(n) CV_MAKETYPE(CV_8U,(n))
隻要認識到,最關鍵的資料類型其實隻有0~6,其他的,都是從0~6擴充通道而已,至于擴充幾維,按照你的實際情況來就好。這裡再解釋一下,0~6的資料類型對應的資料範圍:
無符号8bit整型(最常用):Unsigned 8bits uchar 0~255IplImage: IPL_DEPTH_8U
Mat: CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4
有符号8bit整型:Signed 8bits char -128~127IplImage: IPL_DEPTH_8S
Mat: CV_8SC1,CV_8SC2,CV_8SC3,CV_8SC4
無符号16bit整型:Unsigned 16bits ushort 0~65535IplImage: IPL_DEPTH_16U
Mat: CV_16UC1,CV_16UC2,CV_16UC3,CV_16UC4
有符号16bit整型:Signed 16bits short -32768~32767IplImage: IPL_DEPTH_16S
Mat: CV_16SC1,CV_16SC2,CV_16SC3,CV_16SC4
有符号32bit整型:Signed 32bits int -2147483648~2147483647IplImage: IPL_DEPTH_32S
Mat: CV_32SC1,CV_32SC2,CV_32SC3,CV_32SC4
32bit浮點數:Float 32bits float -1.18*10-38~3.40*10-38IplImage: IPL_DEPTH_32F
Mat: CV_32FC1,CV_32FC2,CV_32FC3,CV_32FC4
64bit浮點數:Double 64bits doubleMat: CV_64FC1,CV_64FC2,CV_64FC3,CV_64FC4
幾種類型之間轉換
要遵循幾個原則:
- 在從小的資料範圍轉向大的資料範圍時,必須先改變類型:
以 CV_8U轉為CV_16U為例~
mat.convertTo(mat,2); //代表的是16U,注意,轉類型的時候不需要考慮通道
mat = mat * 257; //8bit的資料乘以257就轉為了16bit
從大範圍轉小範圍,要先轉再改變類型。還是以16U轉8U為例:
out = mat / 257;
out.convertTo(out, CV_8U);
- 整數類型轉小數類型。
先轉類型再轉資料,遵循這個原則~
Mat img = imread("before.png",IMREAD_UNCHANGED);
cout<<img.type()<<endl;
//先轉為32F
img.convertTo(img, 5);
//再轉為小數
img = img / 65535;
平常我們對Mat做一些比較複雜的運算,都需要搞清楚參數的範圍,最好轉為32F的來進行複雜計算,否則可能會因為溢出和截斷而産生莫名其妙的BUG。
結語
以上就是關于OpenCV Mat類型的相關知識。