我们在创建mat的时候,可以选择的CvType中有很多的选项
CV_8UC1 CV_8SC1 CV_16U C1 CV_16SC1
CV_8UC2 CV_8SC2 CV_16UC2 CV_16SC2
CV_8UC3 CV_8SC3 CV_16UC3 CV_16SC3
CV_8UC4 CV_8SC4 CV_16UC4 CV_16SC4
CV_32SC1 CV_32FC1 CV_64FC1
CV_32SC2 CV_32FC2 CV_64FC2
CV_32SC3 CV_32FC3 CV_64FC3
CV_32SC4 CV_32FC4 CV_64FC4
其实组成都是CV_+深度+通道 其中里面的数字8 ,16,32 标识的是深度
什么是一个Mat的深度,mat的深度有什么意义
CV_8U is unsigned 8bit/pixel - ie a pixel can have values 0-255, this is the normal range for most image and video formats.
CV_32F is float - the pixel can have any value between 0-1.0, this is useful for some sets of calculations on data - but it has to be converted into 8bits to save or display by multiplying each pixel by 255.
CV_32S is a signed 32bit integer value for each pixel - again useful of you are doing integer maths on the pixels, but again needs converting into 8bits to save or display. This is trickier since you need to decide how to convert the much larger range of possible values (+/- 2billion!) into 0-255
大概的意思是说:
CV_8U是无符号8位/像素-即一个像素可以有0-255的值,这是大多数图像和视频格式的正常范围。
CV_32F是float-像素可以有0-1.0之间的任何值,这对于某些数据集的计算很有用-但必须将其转换为8位才能通过将每个像素乘以255来保存或显示。
CV_32S是每个像素的一个有符号32位整数值-同样有用的是,您正在对像素进行整数运算,但同样需要转换为8位才能保存或显示。因为您需要决定如何转换更大范围的可能值(+/-20亿!)变成0-255
其实在mat的属性中有个depth()这个函数,我以为这个求解的就是图片的深度,但是并不是,所以我们千万不能用这个depth()的值作为图片的 深度来理解,这个depth() 是我们在定义mat的时候CV_Type对应的值
CV_8U 0
CV_8S 1
CV_16U 2
CV_16S 3
CV_32S 4
CV_32F 5
CV_64F 6
CV_USRTYPE1 7
这些值和图片的深度还有一定的关联的,比如:
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位;
depth:深度,即每一个像素的位数(bits),那么我们创建的时候就可以知道根据类型也就可以知道每个像素的位数,也就是知道了创建mat的深度
图像深度的意义:
图像深度是指存储每个像素所用的位数,也用于量度图像的色彩分辨率.图像深度确定彩色图像的每个像素可能有的颜色数,或者确定灰度图像的每个像素可能有的灰度级数.
它决定了彩色图像中可出现的最多颜色数,或灰度图像中的最大灰度等级.比如一幅单色图像,若每个象素有8位,则最大灰度数目为2的8次方,即256.
在学习的过程中突然遇到图片的深度,上面是我的理解
不同的深度之间如何进行转换,我们以8UC3 转换为32FC3为例子
public static void main(String[] args) {
try {
ResourceBundle bundle = ResourceBundle.getBundle("opencv");
String opencvDllName = bundle.getString("opencv.dllpath");
System.load(opencvDllName);
} catch (Exception e) {
e.printStackTrace();
}
String filename = "D:\\360MoveData\\Users\\lxn\\Desktop\\opencv\\xf.bmp";
Mat mat = Imgcodecs.imread(filename);//首先是读取图片,默认是是CV_8UC2
Mat submat = mat.submat(10, 200, 10, 200); //为了方便展示我们,截取图片的一部分内容
Mat mat_32F = new Mat(submat.size(), CvType.CV_32FC3);//创建一个32FC3的矩阵
//将8UC3转换为32FC3
for (int i = 0; i < submat.rows(); i++) {
for (int j = 0; j < submat.cols(); j++) {
double[] values = new double[] {};
values = submat.get(i, j);
mat_32F.put(i, j, new double[] { values[0] / 255.0, values[1] / 255.0,values[2] / 255.0 });
}
}
//将32FC3 转换为32SC3
Mat mat_32S = new Mat(submat.size(), CvType.CV_32SC3);
mat_32F.convertTo(mat_32S, CvType.CV_32SC3);
//将32FC3 转换为CV_8UC3
for (int i = 0; i < mat_32S.rows(); i++) {
for (int j = 0; j < mat_32S.cols(); j++) {
double[] values = new double[] {};
values = mat_32F.get(i, j);
mat_32S.put(i, j,new int[] { (int) (values[0] * 255.0), (int) (values[1] * 255.0), (int) (values[2] * 255.0) });
}
}
Mat mat_s = new Mat();
mat_32S.convertTo(mat_s, CvType.CV_8UC3);
HighGui.imshow("测试", mat_s);
HighGui.waitKey();
}
covertTo 这个方法是实现了不同mat之间的类型转换,但是里面的具体的数值还是需要我们*255,或者/255 进行手动的转换
希望对你有所帮助