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

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技术站

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

相关文章

  • Python两个字典键同值相加的几种方法

    当两个字典中存在相同键但对应的值不同时,可以通过多种方法将它们的值相加。 下面介绍几种实现方法: 方法一:循环遍历 可以循环遍历一个字典,并检查该键是否在另一个字典中。如果两个字典中都包含该键,则将它们的对应值加起来并更新到一个新字典中。 dict1 = {"a": 1, "b": 2, "c": …

    python 2023年5月13日
    00
  • Python列表list内建函数用法实例分析【insert、remove、index、pop等】

    以下是详细讲解“Python列表list内建函数用法实例分析【insert、remove、index、pop等】”的完整攻略。 在Python中,列表(list)是种常见数据结构。Python提供了许多内建函数来操作列表,包括insert()、remove()、index()、pop()等。本文将详细绍这些函数的用法,并提供一些示例说明。 insert()函…

    python 2023年5月13日
    00
  • Python代码的打包与发布详解

    下面我将为你详细讲解Python代码的打包与发布的完整攻略。 为什么要打包和发布Python代码 在Python开发中,我们经常会开发一些库或者工具,这些代码需要被其他人使用,此时我们就需要将这些代码进行打包和发布,以便其他人可以轻松地使用我们的代码。 代码打包工具 在Python中,常用的代码打包工具有两个,分别是setuptools和distutils。…

    python 2023年5月14日
    00
  • 如何对csv文件数据分组,并用pyecharts展示

    下面是详细讲解“如何对CSV文件数据分组, 并用pyecharts展示”的完整攻略。 1. 加载csv文件 首先,我们需要读取CSV文件中的数据。一般使用Python内置的CSV模块来读写CSV文件,代码如下: import csv with open(‘data.csv’, ‘r’) as f: reader = csv.reader(f) data = …

    python 2023年6月3日
    00
  • 教你用Python写一个京东自动下单抢购脚本

    教你用Python写一个京东自动下单抢购脚本攻略 1. 编写前准备 在编写京东自动下单抢购脚本前,需要进行以下准备工作: 安装Python环境。Python环境的安装可以参考官方文档Python官方文档。 安装selenium库。selenium是Python中用于Web自动化测试的一个库,也可以用于模拟人的操作。安装selenium可以使用命令:pip i…

    python 2023年5月19日
    00
  • Python手机与电脑游戏脚本的编写方法

    Python手机与电脑游戏脚本的编写方法攻略 一、前言 Python是一个出色的编程语言,而且它在游戏编程方面也有很大的应用,现在许多手机和电脑上的游戏都使用Python进行开发,所以我们应该学习如何编写Python手机与电脑游戏脚本。 二、环境准备 1. 下载Python 首先,我们需要在电脑上安装Python。可以选择去Python官网下载安装包,Pyt…

    python 2023年5月30日
    00
  • 基于Python把网站域名解析成ip地址

    Python提供了socket库,可以用于将网站域名解析为IP地址。以下是详细讲解基于Python把网站域名解析成IP地址的攻略,包含两个例。 示例1:使用socket库解析域名 以下是一个示例,可以使用socket库解析域名: import socket # 解析域名 ip = socket.gethostbyname(‘www.example.com’)…

    python 2023年5月15日
    00
  • python如何设置静态变量

    Python中没有静态变量这个概念,但是可以通过类属性和闭包来实现类似的功能。 使用类属性实现“静态变量” 可以将所需的静态变量定义为类属性,以实现类似的功能。示例如下: class MyClass: static_var = 0 def increment_static_var(cls): cls.static_var += 1 return cls.st…

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