Python 相机位姿变换

这篇具有很好参考价值的文章主要介绍了Python 相机位姿变换。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


项目场景

将自定义数据的影像数据规范化到 2×2 的一个立方体内进行训练。由于影像的相机位置近似在一个平面上,且场景主要在相机位置下方。所以也就是说要把这些相机位姿变换到立方体的上方的表面上。这样训练对象就能落到训练场景内,并在场景内近似居中,有利于训练。其实就是一个求七参数(三个平移量、三个旋转角、一个尺度因子)进行空间直角坐标系转换的过程。由于metashape或者colmap等通过匹配导出的相机位姿通常是以第一张相片的相机坐标系为参考的,那么在进一步处理时就需要对其进行位姿变换(另外也要注意模型中使用的相机坐标系与原始相机坐标系中z轴方向是否一致)。

Python 相机位姿变换,3D,Python,python,数码相机,深度学习

相机位姿

相机位姿(位置和姿态)由相机的外参(extrinsic matrix)决定,投影属性由相机的内参(intrinsic matrix)决定。
相机外参可以用一个 4×4 矩阵来表示,作用是将世界坐标系的点变换到相机坐标系下。所以也常把相机外参矩阵叫做world-to-camera (w2c) 矩阵。相机外参的逆矩阵被称为camera-to-world (c2w) 矩阵,其作用是把相机坐标系的点变换到世界坐标系,也就是常说的位姿矩阵 (poses) 。

c2w矩阵是一个 4x4 的矩阵,c2w[:3,:3]是旋转矩阵R(同时也代表相机姿态,其三个列向量分别代表相机坐标系xyz轴的方向),c2w[:3,3]是平移向量T,c2w[3,3]是尺度因子S。

Python 相机位姿变换,3D,Python,python,数码相机,深度学习
图及描述参考这篇文章,其对相机参数以及NeRF代码解读得很好,推荐阅读。


旋转变换

由于我需要处理的影像的位置基本上是在一个平面上,所以接下来以平面法向量为例计算旋转矩阵来进行旋转变换。

求平面方程

def fit_a_plane(x2, y2, z2):
	"""拟合平面"""
    # 创建系数矩阵A
    A = np.zeros((3, 3))
    for i in range(len(x2)):
        A[0, 0] = A[0, 0] + x2[i] ** 2
        A[0, 1] = A[0, 1] + x2[i] * y2[i]
        A[0, 2] = A[0, 2] + x2[i]
        A[1, 0] = A[0, 1]
        A[1, 1] = A[1, 1] + y2[i] ** 2
        A[1, 2] = A[1, 2] + y2[i]
        A[2, 0] = A[0, 2]
        A[2, 1] = A[1, 2]
        A[2, 2] = len(x2)

    # 创建b矩阵
    b = np.zeros((3, 1))
    for i in range(len(x2)):
        b[0, 0] = b[0, 0] + x2[i] * z2[i]
        b[1, 0] = b[1, 0] + y2[i] * z2[i]
        b[2, 0] = b[2, 0] + z2[i]


    # 求解X矩阵
    A_inv = np.linalg.inv(A)
    X = np.dot(A_inv, b)
    # print('平面拟合结果为:z = %.3f * x + %.3f * y + %.3f' % (X[0, 0], X[1, 0], X[2, 0]))

    # 计算方差
    R = 0
    for i in range(len(x2)):
        R = R + (X[0, 0] * x2[i] + X[1, 0] * y2[i] + X[2, 0] - z2[i]) ** 2
    # print('方差为:%.*f' % (3, R))

    return [X[0, 0], X[1, 0], X[2, 0]]

求法向量

def get_normal_vector(point1, point2, point3):
    '''三个点计算平面法向量'''
    vect1 = np.array(point2) - np.array(point1)
    vect2 = np.array(point3) - np.array(point1)
    norm_vect = np.cross(vect1, vect2)
    return norm_vect

求旋转矩阵

def get_R_matrix( vector_src, vector_tgt):
    """计算两平面(法向量)间的旋转矩阵"""    
    vector_src  =  vector_src / np.linalg.norm( vector_src)
    vector_tgt =  vector_tgt / np.linalg.norm( vector_tgt)
    
    c = np.dot( vector_src,  vector_tgt)
    n_vector = np.cross( vector_src,  vector_tgt)
    
    n_vector_invert = np.array((
        [0, -n_vector[2], n_vector[1]],
        [n_vector[2], 0, -n_vector[0]],
        [-n_vector[1], n_vector[0], 0]))
    
    I = np.eye(3)
    R_w2c = I + n_vector_invert + np.dot(n_vector_invert, n_vector_invert) / (1 + c)
    return R_w2c

平移变换

这个就很简单了,目标中心坐标与相机位置坐标均值作差就得到了平移矩阵

T_move = center_tgt - p_mean

尺度变换

这个也简单,目标尺度与当前所有相机位置边界框尺寸之比就是了

scene_scale = scale_tgt / (p_max - p_min)

变换顺序

  1. 先旋转
  2. 再缩放
  3. 再平移

需要注意的是,一定要把姿态考虑进去,在旋转时对姿态进行同步处理。

以下代码以z=1为目标平面,center_tgt=[0,0,1]为目标中心点坐标。poses为所有相机的c2w位姿矩阵。

# File      :transform_poses.py
# Auther    :WooChi
# Time      :2023/03/15
# Version   :1.0
# Function  :坐标变换到固定场景

def poses_transform(poses,center_tgt=np.array([0, 0, 1])):
	
    # 1. 旋转变换
    # 1.1 拟合平面方程
    f_p = fit_a_plane(poses[:, 0, 3], poses[:, 1, 3], poses[:, 2, 3])

    # 在平面上拿出三个点
    points = np.array([[-1., -1., 0.],
                       [-1., 1., 0.],
                       [1., 1., 0.]])

    points[0, 2] = points[0, 0] * f_p[0] + points[0, 1] * f_p[1] + f_p[2]
    points[1, 2] = points[1, 0] * f_p[0] + points[1, 1] * f_p[1] + f_p[2]
    points[2, 2] = points[2, 0] * f_p[0] + points[2, 1] * f_p[1] + f_p[2]

    # 1.2 计算法向量
    normal_p = get_normal_vector(points[0, :], points[1, :], points[2, :])

    # 目标平面的法向量
    normal_cube = np.array([0., 0., -1.])
    
	# 1.3 求旋转矩阵
    R_w2c = get_R_matrix(normal_p, normal_cube)

    # 1.4 对位置进行旋转变换
    # 先从位姿矩阵中取出位置坐标
    p_src = np.zeros(shape=(len(poses[:, 0, 3]), 3))
    p_src[:, 0] = poses[:, 0, 3]
    p_src[:, 1] = poses[:, 1, 3]
    p_src[:, 2] = poses[:, 2, 3]
	# 再对位置坐标进行旋转变换
    p_new = np.dot(R_w2c, np.transpose(p_src))
    
    # 把变换后的相机位置坐标放到位姿矩阵中
    poses_new = poses.copy()
    poses_new[:, 0, 3] = p_new[0, :]
    poses_new[:, 1, 3] = p_new[1, :]
    poses_new[:, 2, 3] = p_new[2, :]
	
	# 1.5 对姿态进行旋转变换,其实就是对三个列向量(坐标轴)进行旋转变换
    poses_new[:, :3, 0] = np.dot(R_w2c, np.transpose(poses_new[:, :3, 0])).transpose()
    poses_new[:, :3, 1] = np.dot(R_w2c, np.transpose(poses_new[:, :3, 1])).transpose()
    poses_new[:, :3, 2] = np.dot(R_w2c, np.transpose(poses_new[:, :3, 2])).transpose()
	

	# 2. 缩放变换 
    # 2.1 求相机位置坐标所占空间大小
    max_vertices = np.max(p_new, axis=1)
    min_vertices = np.min(p_new, axis=1)
    
    # 2.2 求缩放因子,目标尺寸为2
    scene_scale = 2 / (np.max(max_vertices - min_vertices))

    
    # 2.2. 对位置进行缩放变换
    poses_new[:, :3, 3] *= scene_scale
    p_new[0, :] = poses_new[:, 0, 3]
    p_new[1, :] = poses_new[:, 1, 3]
    p_new[2, :] = poses_new[:, 2, 3]
  

    # 3. 对位置进行平移变换
    T_move = np.array([center_tgt - np.mean(p_new, axis=1)])
    p_new = p_new + T_move.transpose()
	
    poses_new[:, 0, 3] = p_new[0, :]
    poses_new[:, 1, 3] = p_new[1, :]
    poses_new[:, 2, 3] = p_new[2, :]

    return poses_new   

平面拟合
Python 相机位姿变换,3D,Python,python,数码相机,深度学习

位姿变换
Python 相机位姿变换,3D,Python,python,数码相机,深度学习
Python 相机位姿变换,3D,Python,python,数码相机,深度学习


nice.文章来源地址https://www.toymoban.com/news/detail-606073.html

到了这里,关于Python 相机位姿变换的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【计算机视觉:算法和应用】第二章:图像形成——2.3数码相机

    2.1几何图元与变换 2.2相机辐射成像        从一个或多个光源开始,在世界中一个或多个表面反射并通过相机镜头后,光最终到达成像传感器。到达传感器的光子是如何转换为我们在数字图像上看到的数字(R,G,B)值的呢?在这一节,我们构建了一个简单的模型来解释大多数

    2024年01月19日
    浏览(63)
  • 利用ArUco码实现相机位姿估计(Python)

    环境:python3.7 opencv-contrib-python 4.5.1.48 相机标定就是求相机的内参矩阵mtx和畸变系数dist 首先需要利用相机(你需要标定的)拍摄标定板照片,20张左右。拍摄照片的时候各个角度都拍一些,可以变换标定板的位置,但不要大幅度变换相机(不要翻转镜头,上下颠倒相机等等)

    2024年04月28日
    浏览(42)
  • 位姿估计 | 目标体坐标系相对于相机坐标系的位姿估计及其Python代码

    本文接着分享空间目标位姿跟踪和滤波算法中用到的一些常用内容,希望为后来者减少一些基础性内容的工作时间。以往分享总结见文章:位姿跟踪 | 相关内容目录和链接总结(不断更新中~~~) 本文介绍如何 利用特征点求解目标体坐标系相对于相机坐标系的位姿 。 PnP(Pe

    2024年02月10日
    浏览(41)
  • 开源!首个无需相机位姿的通用3D Gaussian Splatting!

    作者 :Hao Li等人|编辑:计算机视觉工坊 添加小助理 :dddvision,备注:3D目标检测,拉你入群。文末附行业细分群 扫描下方二维码,加入3D视觉知识星球,星球内凝聚了众多3D视觉实战问题,以及各个模块的学习资料: 近20门视频课程 (星球成员免费学习)、 最新顶会论文

    2024年04月15日
    浏览(55)
  • (九)相机内参、外参、反透视变换python opencv

    任务需求:将相机上的一个点投影到真实世界平面上去。 原则上单目相机是不可以的,因为只记录了二维信息,真实世界是三维的,双目相机可以通过视差,或者单目+IMU组合,但是 由于特征点在地面上的先验知识 ,因此可以进行反透视变换。方法有很多种那个,这里采用计

    2024年02月06日
    浏览(45)
  • 深度相机(3D相机)

    传统的RGB彩色相机称为2D相机, 只能得到2D的图像信息, 无法得到物体与相机的距离信息,也就是深度信息。 顾名思义, 深度相机除了获取2D信息,还能得到深度信息,也叫RGBD相机, 或3D相机。 顺便提一句, 当前也有很多工作基于2D相机, 通过算法的方式估计深度, 但一

    2024年04月27日
    浏览(24)
  • Python pyglet 自制3D引擎入门(二) -- 绘制立体心形,动画和相机控制

    Python作为目前较广泛的编程语言, 用于制作3D游戏可谓得心应手。本文讲解使用Python pyglet库自制简易3D引擎的方法技巧。 上篇:Python pyglet 自制3D引擎入门(一) – 绘制几何体、创建3D场景 先放效果图: pyglet.window 部分用于实现窗口操作, pyglet.gl 以及 pyglet.gl.glu 模块包含了OpenGL的

    2024年02月10日
    浏览(37)
  • 3D视觉之深度相机方案

    随着机器视觉,自动驾驶等颠覆性的技术逐步发展,采用 3D 相机进行物体识别,行为识别,场景 建模的相关应用越来越多,可以说 3D 相机就是终端和机器人的眼睛。 3D 相机又称之为深度相机,顾名思义,就是通过该相机能检测出拍摄空间的景深距离,这也是与普 通摄像头

    2023年04月21日
    浏览(41)
  • 3D深度相机---结构光

    去年的仪器仪表的课有汇报,我还专门为3D深度像机做了个调研,一直用inter realsense的,最近老师让看结构光方案的,正好总结一下。 由于基于双目立体视觉的深度相机对环境光照强度比较敏感,且比较依赖图像本身的特征,因此在光照不足、缺乏纹理等情况下很难提取到有

    2024年02月02日
    浏览(31)
  • python实现d435i深度相机测量两点之间的距离

    本文介绍python方法实现intel公司realsense系列d435i深度相机测量彩色图像上两点之间的距离。 原理很简单,就是将相机获得的彩色图像流与深度流对齐,这样彩色图像上的每个像素就会对应一个深度值,作为z坐标,然后通过相机内参获得该像素的x坐标和y坐标。我们获得的x、

    2024年02月16日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包