Kinect Azure开发系列(一):深度图的获取及转换显示

您所在的位置:网站首页 深度图像转化成可视点云 Kinect Azure开发系列(一):深度图的获取及转换显示

Kinect Azure开发系列(一):深度图的获取及转换显示

2024-06-07 18:02| 来源: 网络整理| 查看: 265

首先,图像的深度一般是16位的,因为8位的只能表示256个不同的深度值,分辨率太低.对于16位深度数据的显示

法1:16位可以直接转成8位的显示 depth_frame = cv::Mat(depthImage.get_height_pixels(), depthImage.get_width_pixels(), CV_16U, depthImage.get_buffer()); depth_frame.convertTo(depth_out, CV_8U, 1);

这种是直接将16位转成8位,然后,后面设置的是1,也就是低于255的不变,高于的全部转位255,数据的实际信息会丢失.如果设置为很大的值,数据丢失的会更大,详见参考资料中这个函数的原理.

法2: 16位归一化后显示

由于imshow只认0~255的数值,16位的数据可以归一化到0 ~255.

depth_frame = cv::Mat(depthImage.get_height_pixels(), depthImage.get_width_pixels(), CV_16U, depthImage.get_buffer()); normalize(depth_frame, depth_out, 0, 256* 256, NORM_MINMAX); 显示结果

在这里插入图片描述 这里可以点开大图查看,左侧是归一化的结果,出现了很多浅灰色的值,明显起保留了全部的数据信息(细节都保留了),只是缩放到了0~255.但是后者超过255的数据都是255,所以白色面积很大.

补充资料 1.opencv的Mat类型的数据类型

参考这位博主的 里面详细介绍了: (1) cv::Mat的各种类型(位数+基本类型+通道)对应的type的返回值

(2) 不同的通道数对应的单个像素点的数据类型,比如3通道的图像,在单个像素点(i,j)处是一个3维向量,该向量的元素的具体的基本的数据类型才是uchar 或者 short等

2.imshow和imwrite函数 imshow

opencv的imshow函数都只能对像素值处于0-255范围内的图像进行显示。也就是说,无法使用OpenCV提供的接口函数显示诸如CV_16S等非8位数据格式的视差图/深度图,只能转换成CV_8U格式进行操作。 其实,人眼对灰度级的敏感度比较低、根本无法分辨256级灰度值。而对视差图/深度图进行显示,也只是为了比较直观的验证视差图/深度图的准确性(如颜色随距离逐层变化),所以说完全没必要对216 =65536级灰度进行显示,转换成CV_8U格式就能完全满足需求,这也许就是为什么OpenCV没有提供这样接口的原因之一吧。 https://blog.csdn.net/YunLaowang/article/details/86583351

imwrite

而存储的话,imwrite函数在关于保存为不同深度格式时候的图像类型支持说明如下:

8位的图像(CV_8U),支持png/jpg/bmp/webp等各种常见图像格式 16位的图像(CV_16U),支持png/jpeg2000/TIFF格式 32位的图像(CV_32F),支持PFM/TIFF/OpenEXR/TIFF/HDR 在要保存为指定格式之前,可以通过convertTo或者cvtCOLOR进行图像类型或者通道转换之后,再调用imwrite进行保存。

为了显示,利用自带的cv::convertTo函数 参考1 参考2 convertTo的用法 src.convertTo(dst, type, scale, shift)函数 convertTo()函数负责转换数据类型不同的Mat,即可以将类似float型的Mat转换到uchar型的, imwrite()函数能够接受的类型。 而cvtColor()函数是负责转换不同通道的Mat,因为该函数的第4个参数就可以设置目的Mat数据的通道数(只是我们一般没有用到它,一般情况下这个函数是用来进行色彩空间转换的)。 另外也可以不用imwrite()函数来存图片数据,可以直接用通用的XML IO接口函数将数据存在XML或者YXML中。 参考3 注: 函数template _Tp saturate_cast(_Tp2 v)   将参数v转换成模板中的类型,比如说: uchar a = saturate_cast(-100);

4.对非8位的图像数据进行保存 xml文件的格式存储原始数据 txt文件直接存储原始数据,这个其实就是索引到Mat的具体位的元素值,然后存储.实际使用注意修改at后面的数据类型,是uint,float等 这里的方法2是逐个像素的转换,会有信息的丢失,就是超过255的数据会变为255, 16位或32位数据转8位后保存,直接转和归一化以后转,其c++代码如下: 16位图像保存 转换成16位数据后,直接保存,不会引起数据的丢失

// 加载图像 Mat src = imread( "D:/flower.png", IMREAD_UNCHANGED);// IMREAD_UNCHANGED确保按照图像未做任何改变读入,不如按照原位数 printf( "depth %d n", src.depth()); // 转为16位图像 Mat dst; src.convertTo(dst, CV_16U); imshow( "flower16", dst);//未进行归一化,显示是全黑的 imwrite( "D:/flower-16.png", dst);//但是保存的是原始的数据

转换后,归一化以后再保存

Mat src = imread( "D:/flower.png", IMREAD_UNCHANGED); printf( "depth %d n", src.depth()); // 转为16位图像 Mat dst; src.convertTo(dst, CV_16U); // 归一化再保存 normalize(dst, dst, 0, 256* 256, NORM_MINMAX); imwrite( "D:/flower-16.png", dst);//进行了0~255的归一化以后,可以显示 imshow( "flower-16", dst);

32位图像保存

// 加载图像 Mat src = imread( "D:/flower.png", IMREAD_UNCHANGED); printf( "depth %d n", src.depth()); // 转32位图像 Mat dst; src.convertTo(dst, CV_32F); // 归一化再保存 normalize(dst, dst, 0, 1.0, NORM_MINMAX); imwrite( "D:/flower-32.png", dst); imshow( "flower-32", dst);


【本文地址】


今日新闻


推荐新闻


    CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3