原点附近的实数舍入会导致旋转伪影

时间:2012-11-19 21:44:53

标签: c++ rotation rounding

我最近注意到我的旋转算法输出中的异常伪像。我使用的实现将目标矩阵的高密度点投射到源图像上,以计算源像素的贡献的相对比率。缓存这些值以允许通过展开的循环进行非常快速的旋转。

问题是由舍入行为引起的,最好从一维采样策略的背景中说明:

如果中心为0.0且在任一方向上平移0.9,则在舍入时仍为0

short(+0.9) == 0
short(-0.9) == 0

但是如果中心是1.0并且在任一方向上都被翻译为0.9,那么

short(+0.1) == 0
short(+1.9) == 1

距离原点1个单位距离内的任何点都归因于原点 四舍五入。这导致在源图像中落在轴原点附近的点的过采样。解决方案是将浮点坐标深入转换为 执行舍入操作时的正空间并将其转换回来 之后的起源。

我的问题:有没有办法避免这种舍入错误而不转换为正空间?

2 个答案:

答案 0 :(得分:4)

您似乎只需要使用floor函数:

(short)floor(0.9) = 0
(short)floor(-0.9) = -1

答案 1 :(得分:1)

所以显而易见的答案是使用floor函数。这是一个很好的答案,它将解决你的问题。

它确实让您在IEEE浮点数学中遇到(1.0/3.0)*3.0 != 3.0的问题。实际上,static_cast<short>(floor((1.0/3.0)*3.0)) == 2

您可能希望在调用floor之前为您的值添加epsilon。你可能不想使用C风格的演员表,因为有一个合理的理由使用C风格的演员表(google "do not use C-style casts"来了解更多信息),而且那个是古怪的。

所以你想要这样的东西:

short smart_round( double d, double epsilon=0.00001 ) {
  short retval = static_cast<short>(floor( d + epsilon ) );
  return retval;
}

包含epsilon,执行static_cast,并使用floor向下舍入(而不是“向零舍入”的默认C / C ++行为)。

相关问题