torch.atan2函数详细解答

先看看arctan

arctan实际上是用来计算点(x,y)组成的向量,与x轴的弧度的,是tan的反函数,推导如下,α为弧度

y/x=tan alpha

mathrm{arc}tan left( y/x right) =alpha

 y=arctan(x)其图像如下 y为弧度,x为任意值,这里不是指上面的坐标x,y

但这种弧度计算方式是有缺陷的,比如

我想区分如下图A、B两点的弧度,如果AB弧度都是

alpha =mathrm{arc}tan left( -3/4 right) =mathrm{arc}tan left( 3/-4 right)

那么就无法区分开了,也就是虽然x,y有确定的唯一弧度,但同一个弧度会有两个刚好相反的向量指向,比如图中从原点到A和B的两条向量,不能唯一表示一个方向,这也就是atan2解决的东西 

atan2

作用:计算一组点计算点(x,y)组成的向量的弧度,该弧度是与x轴正方向的弧度(这是与传统arctan的唯一区别)

 torch.atan2(input, other, *, out=None) → Tensor

  • input (Tensor) – the first input tensor 是分子,也就是点y的坐标集合

  • other (Tensor) – the second input tensor 是分母,也就是点x的坐标集合,otrher这里填入什么轴的值,就以什么轴的为正方向的夹角的弧度,在二维时other=x,就是该点与x轴正方向的弧度,在三维时other=z,就是该点与z轴正方向的弧度

在三角函数中,atan2是反正切函数的一个变种,有两个变数,主要是提供给计算机编程语言一个简便的弧度计算方式,其定义为:

此时的atan2函数的图像如下,y为弧度,x为任意值

此时指定弧度有了唯一的象限,同一个弧度不会再出现有两条相反方向向量的情况了。

 此时A点的弧度=B的弧度+π,二者的弧度不再相等了,此时弧度相同,因为计算的是与x轴正半轴的弧度,也就是此时确定弧度可以唯一确定一个向量。

 torch.atan2的用法和结果验证

import torch
import numpy as np
from math import pi
x= torch.tensor([1,2,1])
y= torch.tensor([0,pi,2])

result=torch.atan2(y,x)
print(result)

print(np.arctan(pi/2))

tensor([0.0000, 1.0039, 1.1071])
1.0038848218538872

y为input,x为other,arctan(y[0]/x[0]),0=arctan(0/1)

1.0039=arctan(pi/2)

 torch.atan2对于三维空间的使用

在sphere former中,作者使用了如下的网络结构,将xyz转换为(θ,β,radius)的形式,该形式可以唯一地表示一个点。

def cart2sphere(xyz):
    '''
    将xyz坐标转化为弧度坐标[theta, beta, r]
    Args:
        xyz:

    Returns:[theta, beta, r],y与x轴的夹角theta,xy平面上的投影与

    '''
    x, y, z = xyz[:, 0], xyz[:, 1], xyz[:, 2]
    #計算該點於x軸正方向的弧度
    theta = (torch.atan2(y, x) + np.pi) * 180 / np.pi #將弧度值都變爲正值,最後變成角度值,theta 0-360。
    # 計算該點於z軸正方向的弧度
    beta = torch.atan2(torch.sqrt(x**2 + y**2), z) * 180 / np.pi #轉換結果爲角度,第一项永远为正数,也就是y大于0,因此结果y永远为正数 0~180,
    r = torch.sqrt(x**2 + y**2 + z**2)#r是半徑
    return torch.stack([theta, beta, r], -1) 

为什么该形式可以唯一表示一个点呢?

首先,(x,y,z)可以唯一确定1组(θ,β,radius),通过上述代码,(x,y,z)可以得到唯一的一组确定的解。

我们进行分析是否有可能一个(θ,β,radius)可以映射到两个讲过0点的向量(x,y,z)上,

点(x,y,z)可以看做是三个向量x,y,z的合成

theta = (torch.atan2(y, x) + np.pi) * 180 / np.pi

 torch.atan2(y, x)就是上面提到的,一个θ有确定的一个x,y向量。

beta = torch.atan2(torch.sqrt(x**2 + y**2), z) 

该行代码可以计算该点torch.sqrt(x**2 + y**2)(永远在第一、二象限)和z组成的向量与z轴正方向的弧度,因为z在第二个参数位置上,所以是以z轴为正方向。

 也就是x轴现在变为torch.sqrt(x**2 + y**2)/z,y轴变为β,torch.sqrt(x**2 + y**2)永远大于0(图上就是y>0),也就是只有其大于0的部分,对应了这两条曲线,也就是β确定,torch.sqrt(x**2 + y**2)/z唯一确定,如下图,由于torch.sqrt(x**2 + y**2)恒大于0,并不会出现两条完全相反的向量,因此不会出现1个弧度对应两个向量的问题。

 再在该平面上画半径,只有唯一的交点。

也就是θ确定x、y平面上的方向,β确定z,(x+y)平面的方向,半径确定该x,y,z方向上的唯一点。

附:角度与弧度的关系

弧度角度转换

2*pi=2*pi*180°/pi=2*180°=360°

arctan是tan的反函数,而不是倒数的关系