0

最近、回転アルゴリズムの出力に異常なアーティファクトがあることに気付きました。私が使用した実装では、ソース ピクセルからの寄与の相対比率を計算するために、宛先マトリックスからソース イメージに高密度のポイントを投影しました。これらの値は、展開されたループを介して非常に高速な回転を可能にするためにキャッシュされました。

この問題は、丸め動作によって引き起こされました。これは、1 次元のサンプリング戦略のコンテキストから最もよく説明されています。

中心が 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 単位の距離内にあるポイントは、丸めたときに原点に属していました。これにより、ソース イメージの軸の原点近くにあるポイントのオーバーサンプリングが発生しました。解決策は、丸め操作を実行するときに浮動小数点座標を正の空間に深く変換し、後で原点に戻すことでした。

私の質問: 正のスペースに変換せずに、この丸めバグを回避する方法はありますか?

4

2 に答える 2

4

関数を使用するだけでよいようですfloor

(short)floor(0.9) = 0
(short)floor(-0.9) = -1
于 2012-11-19T22:20:39.383 に答える
1

したがって、明白な答えはfloor関数を使用することです。そしてそれは良い答えです、それはあなたの問題を解決します.

(1.0/3.0)*3.0 != 3.0IEEE 浮動小数点数学の問題が残ります。実際、static_cast<short>(floor((1.0/3.0)*3.0)) == 2.

を呼び出す前に、値にイプシロンを追加することをお勧めしますfloor"do not use C-style casts"また、C スタイルのキャストを使用する正当な理由が約 1 つあり (詳細については Googleで調べてください)、それが風変わりであるため、おそらく C スタイルのキャストを使用したくないでしょう。

したがって、次のようなものが必要です。

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

これは を組み込み、epsilonを実行し、それ以外の場合は切り捨てにstatic_cast使用します (デフォルトの C/C++ の「ゼロ方向への丸め」の動作の代わりに)。floor

于 2012-11-19T22:37:24.557 に答える