atan2相关知识汇总

atan2相关知识汇总1 atan2 的含义 C 语言里 doubleatan2 doubley doublex 返回的是原点至点 x y 的方位角 即与 x 轴的夹角

大家好,欢迎来到IT知识分享网。

1.atan2的含义

C 语言里 double atan2(double y,double x) 返回的是原点至点(x,y)的方位角,即与 x 轴的夹角。返回值的单位为弧度,取值范围为(-π, π]。结果为正表示从 X 轴逆时针旋转的角度,结果为负表示从 X 轴顺时针旋转的角度。若要用度表示反正切值,请将结果再乘以 180/π。另外要注意的是,函数atan2(y,x)中参数的顺序是倒置的,atan2(y,x)计算的值相当于点(x,y)的角度值。

atan2相关知识汇总

arctan2的图像表示(维基百科)

atan2相关知识汇总

自己画的atan2的笛卡尔坐标系下的示意图,以及将atan2的范围转换到[0, 2π)的示意图。atan2转换到[0,2π)表示的是与x轴正方向的逆时针夹角,这样转换的好处是便于计算两条线之间的夹角。

参考博客:

https://baike.baidu.com/item/atan2/?fr=aladdin

https://en.wikipedia.org/wiki/Atan2


2.atan2与atan的区别

atan接受的是一个正切值(直线的斜率)得到夹角,但是由于正切的规律性本可以有两个角度的但它却只返回一个,因为atan的值域是从-90~90 也就是它只处理一四象限,所以一般不用它。
atan2(double y,double x) 其中y代表已知点的Y坐标 同理x ,返回值是此点与远点连线与x轴正方向的夹角,这样它就可以处理四个象限的任意情况了,它的值域相应的也就是-180~180了。

例如:
例1:斜率是1的直线的夹角
cout<<atan(1.0)*180/PI;//45°
cout<<atan2(1.0,1.0)*180/PI;//45° 第一象限
cout<<atan2(-1.0,-1.0)*180/PI;//-135°第三象限
后两个斜率都是1 但是atan只能求出一个45°

例2:斜率是-1的直线的角度
cout<<atan(-1.0)*180/PI;//-45°
cout<<atan2(-1.0,1.0)*180/PI;//-45° y为负 在第四象限












cout<<atan2(1.0,-1.0)*180/PI;//135° x为负 在第二象限

常用的不是求过原点的直线的夹角 往往是求一个线段的夹角 这对于atan2就更是如鱼得水了
例如求A(1.0,1.0) B(3.0,3.0)这个线段AB与x轴正方向的夹角
用atan2表示为 atan2(y2-y1,x2-x1) 即 atan2(3.0-1.0,3.0-1.0)


它的原理就相当于把A点平移到原点B点相应变成B’(x2-x1,y2-y1)点

参考博客:https://www.cnblogs.com/dutlei/archive/2013/01/14/2860332.html


3.OpenCV中fastAtan2函数

fastAtan2函数在OpenCV中用户非常广,比如在SIFT描述子求取过程中需要计算特征点的方向,此时OpenCV的源码中就是使用的fastAtan2函数,fastAtan2函数原型如下:
float fastAtan2(float y,float x)
x—向量的x坐标
y—向量的y坐标
输入一个2维向量,计算这个向量的方向,以度为单位(范围是0度—360度),精度是0.3度。




static const float atan2_p1 = 0.94807f*(float)(180/CV_PI); static const float atan2_p3 = -0.40975f*(float)(180/CV_PI); static const float atan2_p5 = 0.63281f*(float)(180/CV_PI); static const float atan2_p7 = -0.092128f*(float)(180/CV_PI); float fastAtan2( float y, float x ) { float ax = std::abs(x), ay = std::abs(y); float a, c, c2; if( ax >= ay ) { c = ay/(ax + (float)DBL_EPSILON); c2 = c*c; a = (((atan2_p7*c2 + atan2_p5)*c2 + atan2_p3)*c2 + atan2_p1)*c; } else { c = ax/(ay + (float)DBL_EPSILON); c2 = c*c; a = 90.f - (((atan2_p7*c2 + atan2_p5)*c2 + atan2_p3)*c2 + atan2_p1)*c; } if( x < 0 ) a = 180.f - a; if( y < 0 ) a = 360.f - a; return a; }

fastAtan2函数得出的角度是以X轴正方向为0°方向,然后角度确定按照逆时针方向,以360°为终点,角度范围0°- 360°。此函数用到的应该是一种快速计算atan2的方法,没有找到出处。但是看到另一种快速计算法:

float ax = std::abs(dx), ay = std::abs(dy); float a = std::min(ax, ay)/(std::max(ax, ay)+(float)DBL_EPSILON); float s = a*a; float r = ((-0.0 * s + 0.) * s - 0.) * s * a + a; if(ay > ax) r = 1. - r; if(dx < 0) r = 3.f - r; if(dy<0) r = -r; //如果这一行改为:if(dy < 0) r = 6.f - r; //结果的取值范围变为[0, 2*PI]

参考博客:

https://blog.csdn.net/mingzhentanwo/article/details/

https://blog.csdn.net/ubunfans/article/details/?utm_source=itdadao&utm_medium=referral

4.fastAtan2与atan2的关系

#include<opencv2\opencv.hpp> using namespace std; using namespace cv; int main() { cv::Point P1(20, 30); //第一象限点 cv::Point P2(-45, 23); //第二象限点 cv::Point P3(-73, -38); //第三象限点 cv::Point P4(29, -47); //第四象限点 cout << "第一象限:P1" << P1 << endl; cout << "atan2: " << atan2(P1.y, P1.x) * 180 / CV_PI << endl; cout << "fastAtan2: " << fastAtan2(P1.y, P1.x) << endl; cout << "第二象限:P2" << P2 << endl; cout << "atan2: " << atan2(P2.y, P2.x) * 180 / CV_PI << endl; cout << "fastAtan2: " << fastAtan2(P2.y, P2.x) << endl; cout << "第三象限:P3" << P3 << endl; cout << "atan2: " << atan2(P3.y, P3.x) * 180 / CV_PI << endl; cout << "fastAtan2: " << fastAtan2(P3.y, P3.x) << endl; cout << "第四象限:P4" << P4 << endl; cout << "atan2: " << atan2(P4.y, P4.x) * 180 / CV_PI << endl; cout << "fastAtan2: " << fastAtan2(P4.y, P4.x) << endl; system("pause"); return 0; } 

结果:

atan2相关知识汇总

通过结果可以发现第一象限和第二象限,atan2(*180 / π)和fastAtan2的值基本相等,第三象限和第四象限,fastAtan2的值基本等于360 + atan2(*180 / π)。可以理解为,fastAtan2实现了将atan2的范围转换到[0, 360).

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/126271.html

(0)
上一篇 2025-09-20 13:00
下一篇 2025-09-20 13:15

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信