上一节我们介绍了像素滤波器,下面介绍另一个实时平滑深度图的机制–加权移动平均机制。
3.2 加权移动平均机制
我们通过观察可以发现,即使kinect采集的是一个静止的场景,在得到的深度图上,同一个像素位置对应的深度值也是在不断变化的,这被称为闪动效应(flickering effect),它是由于随机噪声引起的。 如果要求稳定的深度值,就要尽量避免这种闪动效应。我们的办法是这样的: - 首先,用一个队列存储当前深度帧的前N个深度帧。因为队列是一个FIFO(先进先出)的集合对象,非常适合处理一系列时间离散的数据集。 - 然后,我们根据时间给这N个帧权值,时间最近的深度值权值最大,表示最重要,距离时间最远的帧权值最小,表示最不重要。 - 最后,新的深度帧就由队列中的这些深度帧加权平均得到。注意,这个方法对于静止的场景效果很好,但是当有人物在场景中运动时,因为新的深度帧要依据之前的深度帧,所以我们可能会看到一些动作的残影,这时你需要调整一下权值参数和N的大小。
3.2.1 代码
int N =
5;
UINT16 sumDepthData[
424 *
512] = {
0 };
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
{
memcpy(queDepthArrays.back(), depthData,
424 *
512 *
2);
}
int Denominator =
0;
int Count =
1;
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);
}
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。
转载请注明原文地址: https://ju.6miu.com/read-676482.html