我需要一个非常快速的atan2来获得sobel值的渐变(我正在实施canny edge algo。)。有没有人知道一个非常快的实现,最好是内在函数(SIMD)或非常快速的近似。 (我认为近似值就足够了,因为这些值是四舍五入到0°,45°,90°,135°)
提前致谢
ADD:我知道SVML中的intel的IPP atan2很遗憾我无法使用它。
答案 0 :(得分:2)
您似乎希望舍入到八进制数字,大概从-22.5°
到337.5°
以45°
为增量。
通过等式
将八分音线通过原点分开Y = X tan(Θ),
或
a.Y - b.X = 0.
有适当的缩放因子。
通过计算四个所需角度的这些表达式的符号,您将找到八分圆。通过巧妙的组合,您可以限制为三个符号评估,因为有8=2³
种可能性。
这可以通过计算判别式表达式,它们的符号以及它们的符号的合适组合来使用SIMD指令进行评估,但这并非易事。
可能不需要转换为45°的倍数,甚至不需要顺序编号。这一切都取决于你对八分圆信息的处理方式。
其他SIMD建议:
使用预加载系数,您可以使用16位整数运算(可能使用乘法和加法)计算(X,Y)对中的所有四个线方程。然后获取符号并使用_mm_movemask_epi8
将它们打包到四位。使用四位值作为小型查找表的输入。
答案 1 :(得分:-1)
如上所述here atan2()
已经是单个FPU指令:x87 FPU操作码FPATAN
。只需看一下调用std::atan2()
时编译器生成的反汇编。如果它不是单个FPU指令,那么您可以在GCC内联汇编中尝试this:
inline double my_atan2 (double y, double x) {
double result;
asm (
"fpatan\n\t"
: "=t" (result) // outputs; t = top of fpu stack
: "0" (x), // inputs; 0 = same as result
"u" (y) // u = 2nd floating point register
);
return result;
}