当前位置: 代码迷 >> 综合 >> kinect 2.0 深度图像与彩色图像的校准(坐标映射)+鼠标点击读取深度图坐标及对应的深度距离(两种做法的对比)
  详细解决方案

kinect 2.0 深度图像与彩色图像的校准(坐标映射)+鼠标点击读取深度图坐标及对应的深度距离(两种做法的对比)

热度:81   发布时间:2023-11-25 06:05:06.0

开发环境:

      OpenCV3.4.0 (显示界面库 vc14库)

      KinectSDK-v2.0-PublicPreview1409-Setup (Kinect SDK驱动版本)

      Windows 10(操作系统)    

工作:

介绍了两种方法去做深度图像和彩色图像的校准。

(1).二代深度图:512*424,彩色图:1920*1080,所以说如何进行两者的一个校准呢?我借鉴了很多博客,用

https://blog.csdn.net/shihz_fy/article/details/43602393# 博主的方法做的,按照他的方法我做了些改变,主要是想得到

用鼠标获得的某空间点的空间位置(x,y,z)这是我想要的。但是后面结果出来的,恐怕不是我想的那样。见下图:  

结果图,后台提供代码下载链接

     个人觉得这个方法偷懒了,不是很好的。至少我的目的没有达到。总结起来就是,先测量了深度图和彩色图上同一边长的比例,测量结果是1.437x2=2.874;然后在Opencv里按这个比例把两幅图调整成同样大小,深度图尺寸放大1.437倍,彩色图尺寸缩小一半;最后考虑到边缘的配准效果不好,因此只保留和显示中间配准好的矩形区域。这个方法相当于只做了尺寸变换,还真是简单粗暴啊。另外2.874的比例应该是图内物体长度的比例,而不是图片的比例吧。

     我觉得我得了解一个问题:深度图,输出是什么?除了深度值,还有什么吗?

    回答:深度信息:

       在Kinect 2.0中,深度坐标空间的范围是(高*宽 = 424*512)(官网有说明)。从深度信息Frame中提取数据,主要就是把Frame中的数据转存到一个数组中(官网链接:https://docs.microsoft.com/en-us/previous-versions/windows/kinect/dn772983(v=ieb.10))。

代码为:

  1. pBodyIndexFrame->CopyFrameDataToArray(cDepthHeight * cDepthWidth, bodyIndexArray);  

     这里cDepthHeight是424,cDepthWidth是512,bodyIndexArray就是一个424*512大小的16位unsigned int数组,用来存储深度数据。此帧的数据存储为16位无符号整数,其中每个值表示毫米的距离。

     也就是说深度图得到的就是深度数据而已。。嗯嗯 。难受。。那么不是说点云数据是由深度图来做的吗?那么接下来我想做的应该是获取点云数据,那么就能得到空间点的空间坐标了吧,所以我这个得到的不是真正的空间点的坐标(x,y,z)。


(2) 我再找了资料说:深度空间映射到彩色图像空间常用于背景消除。只需要先从人物索引图像中确定哪些深度像素属于用户,然后通过坐标映射,找到对应的彩色值。也就是明确目标,为什么会有深度空间映射到彩色图像的做法

深度图映射到彩色图

这里用深度图映射到彩色图展示Coordinate mapping类的功能。

注意映射的概念,比如深度图映射到彩色图的意思是对于深度图上的一个像素,找到彩色图上的一个像素与之对应(与函数中x到y的映射概念类似)。

1,获得深度帧:
hr = m_pDepthFrameReader->AcquireLatestFrame(&m_pDepthFrame);

2.保存深度数据到数组:

UINT16 *depthData = new UINT16[424*512];
hr = m_pDepthFrame->CopyFrameDataToArray(424 * 512, depthData);
3,获得坐标映射器:
ICoordinateMapper* m_pCoordinateMapper; hr = m_pKinectSensor->get_CoordinateMapper(&m_pCoordinateMapper);
4.进行映射

HRESULT hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(512 * 424, depthData, 512 * 424, m_pColorCoordinates);

这里m_pColorCoordinates是最终得到的512*424大小的数组,元素为一个个坐标,代表了对应的彩色图上的坐标。

5.显示:

Mat i_depthToRgb(424, 512, CV_8UC4);
if (SUCCEEDED(hr))
{for (int i = 0; i < 424 * 512; i++){ColorSpacePoint p = m_pColorCoordinates[i];if (p.X != -std::numeric_limits<float>::infinity() && p.Y != -std::numeric_limits<float>::infinity()){int colorX = static_cast<int>(p.X + 0.5f);int colorY = static_cast<int>(p.Y + 0.5f);if ((colorX >= 0 && colorX < 1920) && (colorY >= 0 && colorY < 1080)){i_depthToRgb.data[i*4] = i_rgb.data[(colorY * 1920 + colorX)*4];i_depthToRgb.data[i*4 + 1] = i_rgb.data[(colorY * 1920 + colorX) * 4+1];i_depthToRgb.data[i*4 + 2] = i_rgb.data[(colorY * 1920 + colorX) * 4+2];i_depthToRgb.data[i*4 + 3] = i_rgb.data[(colorY * 1920 + colorX) * 4+3];}}}
}
imshow("rgb2depth", i_rgbToDepth);if (waitKey(1) == VK_ESCAPE)break;

结果如下:


方法2 实现了如上的结果,所以可见方法1当中借鉴的博主说:看介绍知道里面有一个成员函数MapDepthFrameToColorSpace可以实现深度图和彩色图的坐标校准,于想试试看,结果转到定义处才发现这个成员函数是纯虚函数!就有点打脸了哦(调皮一下,原作者不要怪我呀),最后,非常感谢你们的分享。

注意下:

 因为  setMouseCallback("rgb2depth", onMouse, &mDepthImg);//mDepthImg是Mat  所以上图有点点区别

      HRESULT hr = m_pCoordinateMapper->MapDepthFrameToColorSpace(512 * 424, depthData, 512 * 424, m_pColorCoordinates);   // 注意这里的彩色点数要写成424*512,至于为什么。可能是为了代表下一个参数colorSpacePoints的大小


参考:(感谢你们!!前人栽树,后人乘凉)

 https://blog.csdn.net/l297969586/article/details/78930661

    Kinect V2.0得到RGB图像各个像素点对应的三维坐标(相机坐标系)

https://blog.csdn.net/shihz_fy/article/details/43602393#

     Kinect深度图与彩色图的坐标校准

https://blog.csdn.net/jiaojialulu/article/details/53088170

     kinect 2.0 SDK学习笔记(二)--坐标映射

 代码下载:

   https://download.csdn.net/download/qq_37791134/10501458

  相关解决方案