Python实现三维世界坐标向二维像素坐标的转换(附源码)

Autonomous vehicle 杂谈_01


一. 坐标转换的过程
  1. 总过程:
    在这里插入图片描述
  2. 分步实现
    世界坐标转换为相机坐标
    在这里插入图片描述
    相机坐标转换为图像坐标
    在这里插入图片描述
    图像坐标转换为像素坐标
    在这里插入图片描述

PS: 世界坐标: (Xw, Yw, Zw)、 相机坐标:(Xc, Yc, Zc)、 图像坐标:(x, y)、 像素坐标: (u, v)、 相机焦距: f、 旋转矩阵:R、 平移矩阵: T

PS: 本文代码不够准确,请移步至博主更新版博文:Python实现激光雷达点云的向图像的重投影(世界坐标转换为像素坐标 + Autoware标定结果使用方法)- - 附源码 * 更新版 - -

二. 需要做的前期准备
  1. 通过 calibration 得到的相机内外参数
  2. set up 一个用于存放py源码(.py)、待转换三维坐标(.txt)__ps: 格式为(Xw,Yw,Zw)、转换二维坐标结果(.txt)的文件夹,大概就是像下边图片中的一样
    by demo
  3. 随便一个可以run python文件的IDE
三. 源码如下(需要更改自己的相机参数)
# 实现三维坐标向二维坐标的转换 

import numpy as np

"""相机内、外参矩阵"""

# 外参矩阵 (需要改)
Out = np.mat([
    [-0.117, -0.992, 0.028, -0.125],
    [-0.0033, -0.0278, -0.9996, 0.2525],
    [0.993, -0.1174, 0.00000315, 0.0716],
    [0, 0, 0, 1]
])

# 内参矩阵 (需要改)
K = np.mat([
    [610.53, 0, 368.114],
    [0, 605.93, 223.969],
    [0, 0, 1]
])

"""坐标转换"""
# 打开用于存放世界坐标的txt文件,将其中的以字符串格式保存的世界坐标转换成(Xw, Yw, Zw, 1)的元组格式
f = open('database', 'r')
database = []
for line in f.readlines():
    coordinate = line.strip()  # 去掉左右的空格符
    coordinate = eval(coordinate)  # 将字符串格式的坐标转换为元组格式
    database.append(coordinate)
# print(database)

world_coordinate_list = []
for item in database:
    world_coordinate_part = (item[0], item[1], item[2], 1)
    world_coordinate_list.append(world_coordinate_part)
# print(world_coordinate_list)


pixel_coordinate_list = []

for item in world_coordinate_list:
    world_coordinate = np.mat([
        [item[0]],
        [item[1]],
        [item[2]],
        [item[3]]
    ])
    print(f'世界坐标为:\n{world_coordinate}')
    # print(type(world_coordinate))
    
    # 世界坐标系转换为相加坐标系 (Xw,Yw,Zw)--> (Xc,Yc,Zc)
    camera_coordinate = Out * world_coordinate
    print(f'相机坐标为:\n{camera_coordinate}')
    Zc = float(camera_coordinate[2])
    print(f'Zc={Zc}')

    # 相机坐标系转图像坐标系 (Xc,Yc,Zc) --> (x, y)  下边的f改为焦距
    focal_length = np.mat([
        [f, 0, 0, 0],
        [0, f, 0, 0],
        [0, 0, 1, 0]
    ])
    image_coordinate = (focal_length * camera_coordinate) / Zc
    print(f'图像坐标为:\n{image_coordinate}')

    # 图像坐标系转换为像素坐标系
    pixel_coordinate = K * image_coordinate
    print(f'像素坐标为:\n{pixel_coordinate}')
    pixel_coordinate_list.append(pixel_coordinate)
    print('---------------------分割线--------------------------------')

print(pixel_coordinate_list)
f = open("result.txt", "w", encoding="utf-8")
for item in pixel_coordinate_list:
    f.write(str(item)+'\n')
    f.write('------------分割线-----------------'+'\n')
f.close()

坐标转换方法参考:https://blog.csdn.net/guyuealian/article/details/104184551
如有问题,敬请指正。欢迎转载,但请注明出处。
EPnP(Efficient Perspective-n-Point)是一种用于计算相机的姿态和三维世界坐标之间关的求解方法。在EPnP算法中,根据相机的内参矩阵和2D像素坐标,可以计算出相机的旋转矩阵和平移向量,进而推导出真实世界中的三维物体坐标。 在Python中,可以使用OpenCV库来实现EPnP算法的代码。下面是一个简单的示例代码: ```python import cv2 import numpy as np # 2D像素坐标 image_points = np.array([[100, 200], [300, 400], [500, 600]], dtype=np.float32) # 对应的真实三维坐标 world_points = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]], dtype=np.float32) # 相机内参矩阵 camera_matrix = np.array([[fx, 0, cx], [0, fy, cy], [0, 0, 1]], dtype=np.float32) # 失真数 dist_coeffs = np.zeros((4, 1)) # 使用EPnP算法求解姿态矩阵和三维坐标 _, rvec, tvec, _ = cv2.solvePnPRansac(world_points, image_points, camera_matrix, dist_coeffs) # 旋转向量转换为旋转矩阵 rot_matrix, _ = cv2.Rodrigues(rvec) # 输出结果 print("旋转矩阵:") print(rot_matrix) print("平移向量:") print(tvec) ``` 在这个示例代码中,我们首先定义了2D像素坐标和对应的真实三维坐标,然后定义了相机的内参矩阵和失真数。接下来,使用`cv2.solvePnPRansac`函数来求解姿态矩阵和三维坐标。最后,将旋转向量转换为旋转矩阵,并输出结果。 当然,实际应用时,我们还需要进行一些图像预处理、特征点提取和匹配等步骤,来得到准确的2D像素坐标。这里只是简单展示了EPnP算法的实现过程,具体的应用场景还需要根据实际情况进行调整和优化。
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值