kinect 2.0 SDK学习笔记(六)--深度图的实时平滑之加权移动平均机制
2016-11-17 22:59
323 查看
上一节我们介绍了像素滤波器,下面介绍另一个实时平滑深度图的机制–加权移动平均机制。
如果要求稳定的深度值,就要尽量避免这种闪动效应。我们的办法是这样的:
- 首先,用一个队列存储当前深度帧的前N个深度帧。因为队列是一个FIFO(先进先出)的集合对象,非常适合处理一系列时间离散的数据集。
- 然后,我们根据时间给这N个帧权值,时间最近的深度值权值最大,表示最重要,距离时间最远的帧权值最小,表示最不重要。
- 最后,新的深度帧就由队列中的这些深度帧加权平均得到。注意,这个方法对于静止的场景效果很好,但是当有人物在场景中运动时,因为新的深度帧要依据之前的深度帧,所以我们可能会看到一些动作的残影,这时你需要调整一下权值参数和N的大小。
如果在实时采集深度图的情况下,可以看到背景上像素的闪动效应明显减小了。
完整的实时深度图平滑(像素滤波+加权移动平均)代码链接
请自行配制环境–kinect 2.0SDK和OpenCV。
3.2 加权移动平均机制
我们通过观察可以发现,即使kinect采集的是一个静止的场景,在得到的深度图上,同一个像素位置对应的深度值也是在不断变化的,这被称为闪动效应(flickering effect),它是由于随机噪声引起的。如果要求稳定的深度值,就要尽量避免这种闪动效应。我们的办法是这样的:
- 首先,用一个队列存储当前深度帧的前N个深度帧。因为队列是一个FIFO(先进先出)的集合对象,非常适合处理一系列时间离散的数据集。
- 然后,我们根据时间给这N个帧权值,时间最近的深度值权值最大,表示最重要,距离时间最远的帧权值最小,表示最不重要。
- 最后,新的深度帧就由队列中的这些深度帧加权平均得到。注意,这个方法对于静止的场景效果很好,但是当有人物在场景中运动时,因为新的深度帧要依据之前的深度帧,所以我们可能会看到一些动作的残影,这时你需要调整一下权值参数和N的大小。
3.2.1 代码
// 前帧数量N int N = 5; // 各个像素深度值总和 UINT16 sumDepthData[424 * 512] = { 0 }; // 初始化,将前N帧入队列 if (queDepthArrays.size() < N) { UINT16 *temp = new UINT16[424 * 512]; memcpy(temp, depthData, 424 * 512 * 2); queDepthArrays.push_back(temp); } else { if (queDepthArrays.size() == N) { // 队列中加入当前帧 UINT16 *temp = new UINT16[424 * 512]; memcpy(temp, depthData, 424 * 512 * 2); queDepthArrays.push_back(temp); } else { // 队列中加入当前帧,queDepthArrays.back()相当于当前帧,因此只需要更新它 memcpy(queDepthArrays.back(), depthData, 424 * 512 * 2); } // 队列中已存满N个前帧+一个当前帧 // Denominator表示分母,count表示权值的分子 int Denominator = 0; int Count = 1; // 我们首先创建一个空的深度图,每个像素位置上储存前N帧加当前帧深度值加权之和 // 最后每个像素除以权值之和 for each (auto item in queDepthArrays) { // 处理每行像素 for (int depthArrayRowIndex = 0; depthArrayRowIndex < 424; depthArrayRowIndex++) { // 处理每个像素 for (int depthArrayColumnIndex = 0; depthArrayColumnIndex < 512; depthArrayColumnIndex++) { int index = depthArrayColumnIndex + (depthArrayRowIndex * 512); sumDepthData[index] += item[index] * Count; } } Denominator += Count; Count++; } // 除以权值之和 for (int i = 0; i<512 * 424;i++) { queDepthArrays.back()[i] = depthData[i]; averagedDepthData[i] = (short)(sumDepthData[i] / Denominator); } // 相当于queue.pop() auto temp = queDepthArrays.begin(); for (auto iter = queDepthArrays.begin(); iter !=queDepthArrays.end()-1; iter++) { *iter = *(iter + 1); } queDepthArrays.back() = *temp; }
3.2.2 显示效果
为了方便对比,我将N调的比较大,可以看到我手臂挥动的残影。如果在实时采集深度图的情况下,可以看到背景上像素的闪动效应明显减小了。
完整的实时深度图平滑(像素滤波+加权移动平均)代码链接
请自行配制环境–kinect 2.0SDK和OpenCV。
相关文章推荐
- kinect 2.0 SDK学习笔记(五)--深度图的实时平滑之像素滤波器
- kinect 2.0 SDK学习笔记(四)--深度图与彩色图对齐
- C# Kinect 2.0 SDK 学习笔记(1)——彩色影像数据流
- kinect 2.0 SDK学习笔记(七)--matlab自带相机标定程序对kinect进行简单标定
- kinect 2.0 SDK学习笔记(二)--坐标映射
- C# Kinect 2.0 SDK 学习笔记(0)——基本情况介绍
- kinect 2.0 SDK学习笔记(一)--获得原始数据
- kinect 2.0 SDK学习笔记(三)--生成3D点云
- Kinect开发学习笔记之(五)不带游戏者ID的深度数据的提取
- Kinect开发学习笔记之(六)带游戏者ID的深度数据的提取(转)
- kinect 学习笔记二(深度图像的利用--抠取用户躯体)
- [学习笔记]实时SLAM的未来及深度学习与SLAM对比
- Kinect学习笔记(五)——更专业的深度图
- Kinect开发学习笔记之(六)带游戏者ID的深度数据的提取
- Kinect学习笔记(六)——深度数据测量技术及应用
- Kinect开发学习笔记之(五)不带游戏者ID的深度数据的提取(转)
- Kinect开发学习笔记之(八)彩色、深度、骨骼和用户抠图结合
- Kinect开发学习笔记之(七)带游戏者ID的深度数据的提取
- kinect学习笔记(二)—— Sdk平台的搭建~、
- Kinect开发学习笔记之(五)不带游戏者ID的深度数据的提取