前言
很多人不重视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~255
IplImage: IPL_DEPTH_8U
Mat: CV_8UC1, CV_8UC2, CV_8UC3, CV_8UC4
有符号8bit整型:Signed 8bits char -128~127
IplImage: IPL_DEPTH_8S
Mat: CV_8SC1,CV_8SC2,CV_8SC3,CV_8SC4
无符号16bit整型:Unsigned 16bits ushort 0~65535
IplImage: IPL_DEPTH_16U
Mat: CV_16UC1,CV_16UC2,CV_16UC3,CV_16UC4
有符号16bit整型:Signed 16bits short -32768~32767
IplImage: IPL_DEPTH_16S
Mat: CV_16SC1,CV_16SC2,CV_16SC3,CV_16SC4
有符号32bit整型:Signed 32bits int -2147483648~2147483647
IplImage: IPL_DEPTH_32S
Mat: CV_32SC1,CV_32SC2,CV_32SC3,CV_32SC4
32bit浮点数:Float 32bits float -1.18*10-38~3.40*10-38
IplImage: IPL_DEPTH_32F
Mat: CV_32FC1,CV_32FC2,CV_32FC3,CV_32FC4
64bit浮点数:Double 64bits double
Mat: 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<
//先转为32F
img.convertTo(img, 5);
//再转为小数
img = img / 65535;
平常我们对Mat做一些比较复杂的运算,都需要搞清楚参数的范围,最好转为32F的来进行复杂计算,否则可能会因为溢出和截断而产生莫名其妙的BUG。
结语
以上就是关于OpenCV Mat类型的相关知识。