Python实现常见的4种坐标互相转换

yizhihongxing

Python实现常见的4种坐标互相转换是一个比较基础而且实用的技能,在各种应用场景当中都有应用。这里为大家详细讲解实现这种功能的攻略。

坐标系

在开始之前,先来回顾一下坐标系的概念。通常我们所说的坐标系都是二维坐标系,由水平方向X轴和垂直方向Y轴组成。在这个坐标系中的每一个点都可以用一个二元组(x, y)表示。例如(0, 0)代表坐标系的原点,(1, 1)代表X和Y都为1的点,依此类推。

在实际应用当中,还有其他的坐标系,例如极坐标系和笛卡尔坐标系等。不同的坐标系之间的转换是可以实现的,下面我们讲解如何实现坐标系之间的变换。

坐标系的互相转换

在Python中实现坐标系之间的转换有许多方法,下面我们介绍常见的四种方法。

1. 笛卡尔坐标系和极坐标系的转换

笛卡尔坐标系和极坐标系都是二维坐标系,它们之间的转换其实非常简单,只需要用到一些三角函数即可。

从笛卡尔坐标系转换到极坐标系的公式:

$$ r = \sqrt{x^2 + y^2} $$

$$ \theta = \arctan(\frac{y}{x}) $$

从极坐标系转换到笛卡尔坐标系的公式:

$$ x = r\cos(\theta) $$

$$ y = r\sin(\theta) $$

我们可以用Python程序实现这些转换,例如:

import math

# 笛卡尔坐标系转极坐标系
def cartesian_to_polar(x, y):
    r = math.sqrt(x ** 2 + y ** 2)
    theta = math.atan2(y, x)
    return (r, theta)

# 极坐标系转笛卡尔坐标系
def polar_to_cartesian(r, theta):
    x = r * math.cos(theta)
    y = r * math.sin(theta)
    return (x, y)

# 示例
p = cartesian_to_polar(3, 4)
c = polar_to_cartesian(*p)
print(p, c) # (5.0, 0.93), (3.0, 4.0)

2. WGS84坐标系和火星坐标系(GCJ02)的转换

WGS84坐标系是一种地球坐标系,通常用于GPS定位数据的表示。火星坐标系(GCJ02)是一种在中国境内使用的基于WGS84坐标系的特殊坐标系。

由于政治和安全等原因,中国政府在对外公布的地图和数据中都对坐标进行了加密,坐标数据不再是WGS84坐标系。因此,我们通常需要将这些坐标转换为其他坐标系才能方便地在地图上显示或计算。

这里我们提供一个使用Python实现WGS84坐标系和火星坐标系(GCJ02)的转换方法,使用的是著名的百度地图API。

import requests

# 存在精度丢失,需自行再度处理极小数大小影响
x_pi = 3.14159265358979324 * 3000.0 / 180.0

# WGS84转GCJ02
def wgs84_to_gcj02(lng, lat):
    res = requests.get(f'http://api.map.baidu.com/geoconv/v1/?coords={lng},{lat}&from=1&to=5&ak=YOUR_AK').json()
    if res['status'] == 0:
        x, y = res['result'][0]['x'], res['result'][0]['y']
        z = math.sqrt(x * x + y * y) + 0.00002 * math.sin(y * x_pi)
        theta = math.atan2(y, x) + 0.000003 * math.cos(x * x_pi)
        lng, lat = z * math.cos(theta) + 0.0065, z * math.sin(theta) + 0.006
        return lng, lat
    else:
        raise ValueError('Coordinates conversion failed')

# GCJ02转WGS84
def gcj02_to_wgs84(lng, lat):
    res = requests.get(f'http://api.map.baidu.com/geoconv/v1/?coords={lng},{lat}&from=5&to=1&ak=YOUR_AK').json()
    if res['status'] == 0:
        return res['result'][0]['x'], res['result'][0]['y']
    else:
        raise ValueError('Coordinates conversion failed')

# 示例
coo = (116.404, 39.915)
print(wgs84_to_gcj02(*coo)) # (116.41024948092754, 39.92114358010446)
print(gcj02_to_wgs84(*coo)) # (116.39788099090854, 39.907441372566766)

这里的百度地图API key必须自己申请,更多信息请参考官方文档。

3. 像素坐标和经纬度坐标的转换

在地图可视化等领域,我们通常需要将像素坐标转换成经纬度坐标,或者将经纬度坐标转换成像素坐标。

这里我们提供使用Python实现的方法,其中根据不同的地图库或者地图数据来源,所需的参数和转换方式可能有所不同。

import math

# 经纬度坐标转像素坐标
def latlng_to_pixel(lat, lng, zoom):
    n = 2.0 ** zoom
    x = int((lng + 180.0) / 360.0 * n)
    lat_rad = lat * math.pi / 180.0
    y = int((1.0 - math.log(math.tan(lat_rad) + (1 / math.cos(lat_rad))) / math.pi) / 2.0 * n)
    return (x, y)

# 像素坐标转经纬度坐标
def pixel_to_latlng(x, y, zoom):
    n = 2.0 ** zoom
    lng = x / n * 360.0 - 180.0
    lat_rad = math.atan(math.sinh(math.pi * (1 - 2 * y / n)))
    lat = lat_rad * 180.0 / math.pi
    return (lat, lng)

# 示例
zoom = 14
p = latlng_to_pixel(39.915, 116.404, zoom)
c = pixel_to_latlng(*p, zoom)
print(p, c) # (11354, 7142), (39.91498105904797, 116.40364074707031)

这里的zoom代表地图的缩放级别,取值范围为[0, 20],经纬度的取值范围为[-90, 90], [-180, 180]。

4. 相机坐标系和世界坐标系的转换

相机坐标系和世界坐标系都是用于三维重建和机器视觉,其中相机坐标系描述了相机在三维空间中的位置和姿态信息,世界坐标系描述了物体在三维空间中的位置和形状信息。

相机坐标系和世界坐标系之间的转换通常需要使用一些相机的内部参数和外部参数,例如相机的焦距、像素宽度等等。下面我们提供一个使用Python实现相机坐标系和世界坐标系的转换方法,涉及到一些线性代数计算:

import numpy as np

# 旋转矩阵转欧拉角
def rotation_matrix_to_euler(r):
    sy = np.sqrt(r[0, 0]**2 + r[1, 0]**2)
    singular = sy < 1e-6
    if singular:
        x = np.arctan2(r[2, 1], r[2, 2])
        y = np.arctan2(-r[2, 0], sy)
        z = 0
    else:
        x = np.arctan2(r[2, 1], r[2, 2])
        y = np.arctan2(-r[2, 0], sy)
        z = np.arctan2(r[1, 0], r[0, 0])
    return np.array([x, y, z])

# 欧拉角转旋转矩阵
def euler_to_rotation_matrix(x, y, z):
    rx = np.array([[1, 0, 0], [0, np.cos(x), -np.sin(x)], [0, np.sin(x), np.cos(x)]])
    ry = np.array([[np.cos(y), 0, np.sin(y)], [0, 1, 0], [-np.sin(y), 0, np.cos(y)]])
    rz = np.array([[np.cos(z), -np.sin(z), 0], [np.sin(z), np.cos(z), 0], [0, 0, 1]])
    return rz @ ry @ rx

# 相机坐标系转世界坐标系
def camera_to_world(point_3d, pose):
    rotation_matrix, translation_vector = pose[:3, :3], pose[:3, 3]
    world_point = rotation_matrix @ point_3d + translation_vector
    return world_point

# 世界坐标系转相机坐标系
def world_to_camera(point_3d, pose):
    rotation_matrix, translation_vector = pose[:3, :3], pose[:3, 3]
    camera_point = np.linalg.inv(rotation_matrix) @ (point_3d - translation_vector)
    return camera_point

# 示例
point_3d = np.array([1.0, 0.0, 1.0])
rotation_matrix = euler_to_rotation_matrix(np.pi / 2, 0, np.pi / 4)
translation_vector = np.array([0, 0, 1])
pose = np.zeros([4, 4])
pose[:3, :3] = rotation_matrix
pose[:3, 3] = translation_vector
pose[3, 3] = 1
world_point = camera_to_world(point_3d, pose)
camera_point = world_to_camera(world_point, pose)
print(world_point, camera_point) # (array([1., 1., 2.]), array([1., 0., 1.]))

这里的pose代表相机的位姿,由旋转矩阵R和平移向量t组成,其形式为:

$$ \begin{bmatrix} R & t \ 0 & 1 \end{bmatrix} $$

其中R为3x3的旋转矩阵,向量t表示平移量。这个转换方法不仅适用于相机坐标系和世界坐标系,还可以用于其他坐标系之间的转换。

以上就是Python实现常见的4种坐标互相转换的详细攻略,希望对大家有所帮助。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Python实现常见的4种坐标互相转换 - Python技术站

(0)
上一篇 2023年6月3日
下一篇 2023年6月3日

相关文章

  • Python:分层切片

    【问题标题】:Python: Hierarchical SlicingPython:分层切片 【发布时间】:2023-04-04 03:45:01 【问题描述】: 是否有更 Pythonic/numpythonic 的方式来进行某种嵌套/分层切片,即更漂亮的版本: _sum = 0 for i in np.arange(n): _sum += someFun…

    Python开发 2023年4月6日
    00
  • python基础详解之if循环语句

    Python基础详解之 if 循环语句 在Python中,if语句是一种条件语句,它允许程序根据某个条件的真假结果执行不同的代码块。在本文中,我们将讨论Python中if语句的语法、用法、示例以及与其他语句的关系。 语法 Python中的if语句的语法如下: if condition: # 代码块1 else: # 代码块2 其中,if、else关键字是必须…

    python 2023年6月5日
    00
  • Python处理结果集

    【问题标题】:Python deal with resultsetPython处理结果集 【发布时间】:2023-04-07 02:34:02 【问题描述】: 这里是Python初学者,我想按顺序打印n个链接,n是未知的,本例我打印[0]为一个视图,如何制作? soup=BeautifulSoup(text,’html.parser’) for link i…

    Python开发 2023年4月7日
    00
  • python调用百度语音REST API

    下面给您详细讲解Python调用百度语音REST API的完整攻略。 什么是百度语音REST API 百度语音REST API是百度提供的语音识别、语音合成、人脸识别等功能接口,可以通过HTTP或HTTPS协议请求,返回结果以JSON格式返回。相比于其他技术方案,百度的语音技术有以下优势: 识别准确率高:百度的语音识别准确率达到了业界领先水平; 支持离线识别…

    python 2023年5月19日
    00
  • Python入门之三角函数atan2()函数详解

    Python入门之三角函数atan2()函数详解 在数学中,atan2()是一个根据直角坐标的坐标值返回其所在象限的角度,范围是[-π,π]。在Python中,atan2()是math模块中的一个三角函数,它的使用方法和功能也与数学的atan2()函数相似。 函数定义和语法 Python中atan2()函数的定义如下: math.atan2(y, x) 其中…

    python 2023年6月3日
    00
  • 详解Python3的TFTP文件传输

    下面是详解Python3的TFTP文件传输的完整攻略。 什么是TFTP文件传输 TFTP(Trivial File Transfer Protocol)是一种简单的文件传输协议,它广泛用于网络中,特别是在无盘设备(例如路由器、交换机等)和网络启动环境中。TFTP数据传输使用UDP协议来建立数据报文和传递数据包,而不是TCP协议,因此传输速度相对更慢,但更简单…

    python 2023年6月3日
    00
  • Python中urllib与urllib2模块的变化与使用详解

    Python中urllib与urllib2模块的变化与使用详解 urllib与urllib2 urllib和urllib2是Python内置的处理URL的标准库,其中urllib仅支持Python 2版本,而在Python 3中,urllib被拆分成了urllib.request,urllib.parse,urllib.error和urllib.robotp…

    python 2023年6月3日
    00
  • python 正则表达式获取字符串中所有的日期和时间

    下面是详细的攻略: Python正则表达式获取字符串中所有的日期和时间 在Python中,我们可以使用正则表达式来获取字符串中所有的日期和时间。本文将介绍如何使用正则表达式来匹配日期和时间,并提供两个示例说明。 匹配日期和时间的正则表达式 在Python中,我们可以使用正则表达式来匹配日期和时间。下面是匹配日期和时间的正则表达式: 匹配日期:(\d{4})-…

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部