[Tools: Camera Conventions] NeRF中的相机矩阵估计

这篇具有很好参考价值的文章主要介绍了[Tools: Camera Conventions] NeRF中的相机矩阵估计。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

参考:NeRF代码解读-相机参数与坐标系变换 - 知乎

  • 在NeRF中,一个重要的步骤是确定射线(rays)的初始点方向
  • 根据射线的初始点和方向,和设定射线深度和采样点数量,可以估计该射线成像的像素值。
  • 估计得到的像素值,在训练中用于计算损失更新参数,在测试中用于渲染图像。

[Tools: Camera Conventions] NeRF中的相机矩阵估计,数码相机,NeRF,相机参数

相机矩阵包含内参和外参矩阵:

  • 计算相机坐标系在图片坐标系中的坐标:相机内参矩阵;
  • 计算世界坐标系在相机坐标系中的坐标:相机外参矩阵。

确定射线的初始点和方向,通常是上述过程的逆过程,通常包含两个步骤:

  • 计算图片坐标系在相机坐标系中的坐标;
  • 计算相机坐标系在世界坐标系中的坐标:c2w矩阵。

目录

1. 计算c2w矩阵

2. 根据相机内参,计算射线在相机坐标系下的方向

3. 根据c2w矩阵和相机坐标系下的方向,计算射线在世界坐标系下的方向和初始位置


1. 计算c2w矩阵

在NeRF中,通常使用相机外参矩阵的逆矩阵,也即:camera-to-world (c2w)矩阵。c2w矩阵左乘相机坐标系下的坐标,即可得到世界坐标系下的坐标。给定世界坐标系和相机坐标系,可以计算c2w矩阵:

[Tools: Camera Conventions] NeRF中的相机矩阵估计,数码相机,NeRF,相机参数

以上图的世界坐标系和NeRF中使用的相机坐标系为例:

  1. 根据给定的相机的elevation, azimuth和camera_distance,计算相机在世界坐标系下的坐标
  2. 根据相机在世界坐标系下的坐标,计算相机的朝向
  3. 根据相机在世界坐标系下的坐标和朝向(X_C, Y_C, Z_C),组成c2w矩阵。

[Tools: Camera Conventions] NeRF中的相机矩阵估计,数码相机,NeRF,相机参数

# elevation: X_W -> Y_W
# azimuth: X_w -> Z_W
# camera_distance: 相机距离原点的距离
# camera_position的顺序是(x, y, z)

camera_positions = torch.stack(
    [
        camera_distance * torch.cos(elevation) * torch.cos(azimuth),
        camera_distance * torch.sin(elevation),
        camera_distance * torch.cos(elevation) * torch.sin(azimuth),
    ],
    dim=-1,
)
# default scene center at origin
center = torch.zeros_like(camera_positions)
# default camera up direction as +z
up = torch.as_tensor([0, 1, 0], dtype=torch.float32)
# fovy = torch.tensor(fovy_deg * math.pi / 180, dtype=torch.float32)

lookat = F.normalize(center - camera_positions, dim=-1)
right = F.normalize(torch.cross(lookat, up), dim=-1)
up = F.normalize(torch.cross(right, lookat), dim=-1)
# default setting
c2w3x4 = torch.cat(
    [torch.stack([right, up, -lookat], dim=-1), camera_positions[:, None]],
    dim=-1,
)

c2w = torch.cat(
    [c2w3x4, torch.zeros_like(c2w3x4[:1])], dim=0
)
c2w[3, 3] = 1.0

2. 根据相机内参,计算射线在相机坐标系下的方向

之后根据fovy/focal length,以及图片height和width确定相机内参矩阵(没有标准化):文章来源地址https://www.toymoban.com/news/detail-611463.html

def get_ray_directions(
        H: int,
        W: int,
        focal: Union[float, Tuple[float, float]],
        principal: Optional[Tuple[float, float]] = None,
        use_pixel_centers: bool = True,
) -> Float[Tensor, "H W 3"]:
    """
    Get ray directions for all pixels in camera coordinate.
    Reference: https://www.scratchapixel.com/lessons/3d-basic-rendering/
               ray-tracing-generating-camera-rays/standard-coordinate-systems

    Inputs:
        H, W, focal, principal, use_pixel_centers: image height, width, focal length, principal point and whether use pixel centers
    Outputs:
        directions: (H, W, 3), the direction of the rays in camera coordinate
    """
    pixel_center = 0.5 if use_pixel_centers else 0

    if isinstance(focal, float):
        fx, fy = focal, focal
        cx, cy = W / 2, H / 2
    else:
        fx, fy = focal
        assert principal is not None
        cx, cy = principal

    i, j = torch.meshgrid(
        torch.arange(W, dtype=torch.float32) + pixel_center,
        torch.arange(H, dtype=torch.float32) + pixel_center,
        indexing="xy",
    )

    directions: Float[Tensor, "H W 3"] = torch.stack(
        [(i - cx) / fx, -(j - cy) / fy, -torch.ones_like(i)], -1
    )

    return directions

# 相机内参矩阵
intrinsic = torch.tensor([
    [focal_length * width, 0, 0.5 * width], 
    [0, focal_length * height, 0.5 * height], 
    [0, 0, 1]]
)

# 计算射线方向
directions = get_ray_directions(
            height, width,
            (intrinsic[0, 0], intrinsic[1, 1]),
            (intrinsic[0, 2], intrinsic[1, 2]),
            use_pixel_centers=False)

3. 根据c2w矩阵和相机坐标系下的方向,计算射线在世界坐标系下的方向和初始位置

def get_rays(
        directions: Float[Tensor, "... 3"],
        c2w: Float[Tensor, "... 4 4"],
        keepdim=False,
        noise_scale=0.0,
) -> Tuple[Float[Tensor, "... 3"], Float[Tensor, "... 3"]]:
    # Rotate ray directions from camera coordinate to the world coordinate
    assert directions.shape[-1] == 3

    if directions.ndim == 2:  # (N_rays, 3)
        if c2w.ndim == 2:  # (4, 4)
            c2w = c2w[None, :, :]
        assert c2w.ndim == 3  # (N_rays, 4, 4) or (1, 4, 4)
        rays_d = (directions[:, None, :] * c2w[:, :3, :3]).sum(-1)  # (N_rays, 3)
        rays_o = c2w[:, :3, 3].expand(rays_d.shape)
    elif directions.ndim == 3:  # (H, W, 3)
        assert c2w.ndim in [2, 3]
        if c2w.ndim == 2:  # (4, 4)
            rays_d = (directions[:, :, None, :] * c2w[None, None, :3, :3]).sum(
                -1
            )  # (H, W, 3)
            rays_o = c2w[None, None, :3, 3].expand(rays_d.shape)
        elif c2w.ndim == 3:  # (B, 4, 4)
            rays_d = (directions[None, :, :, None, :] * c2w[:, None, None, :3, :3]).sum(
                -1
            )  # (B, H, W, 3)
            rays_o = c2w[:, None, None, :3, 3].expand(rays_d.shape)
    elif directions.ndim == 4:  # (B, H, W, 3)
        assert c2w.ndim == 3  # (B, 4, 4)
        rays_d = (directions[:, :, :, None, :] * c2w[:, None, None, :3, :3]).sum(
            -1
        )  # (B, H, W, 3)
        rays_o = c2w[:, None, None, :3, 3].expand(rays_d.shape)

    # add camera noise to avoid grid-like artifect
    # https://github.com/ashawkey/stable-dreamfusion/blob/49c3d4fa01d68a4f027755acf94e1ff6020458cc/nerf/utils.py#L373
    if noise_scale > 0:
        rays_o = rays_o + torch.randn(3, device=rays_o.device) * noise_scale
        rays_d = rays_d + torch.randn(3, device=rays_d.device) * noise_scale

    rays_d = F.normalize(rays_d, dim=-1)
    if not keepdim:
        rays_o, rays_d = rays_o.reshape(-1, 3), rays_d.reshape(-1, 3)

    return rays_o, rays_d
rays_o, rays_d = get_rays(directions, c2w.unsqueeze(0), keepdim=True)

到了这里,关于[Tools: Camera Conventions] NeRF中的相机矩阵估计的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • U盘/硬盘/数码相机RAW格式文件丢失的原因|恢复方法

    在现代数字生活中,U盘、硬盘以及数码相机等设备已经成为我们储存和分享数据的主要工具。然而,当这些设备中的RAW格式文件出现丢失时,我们可能会陷入困境。面对这种情况,了解如何恢复这些RAW格式文件就变得至关重要。 一、理解RAW格式文件 RAW格式文件是一种原始数

    2024年02月12日
    浏览(60)
  • 小米12s ultra,索尼xperia1 iv,数码相机 拍照对比

    首先说明所有的测试结果和拍摄数据我放到百度网盘了(地址在结尾) 我一直想知道现在的手机和相机差距有多大,到底差在哪儿? 先说结论: 1.1英寸的手机cmos(2022年) 6年前(2016)的入门款相机(m43画幅) 2.手机 不能换镜头,只能在特定的拍摄距离才能发挥出全部的实力.数码变焦画质损

    2024年02月09日
    浏览(87)
  • 【计算机视觉:算法和应用】第二章:图像形成——2.3数码相机

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

    2024年01月19日
    浏览(67)
  • 【NeRF】相机的内外参是什么?单目相机是如何成像的?

    在做Nerf时对其中的一些原理感到困惑,因而把这些基础理论知识总结下来,方便后面的学习。 对于围绕某一物体拍出来的一组照片而言,我们首先需要弄清不同照片拍摄的方位,如下图所示。而相机的内外参就是用来表达相机位置的参数。其中,相机的位置和朝向由相机的

    2024年02月16日
    浏览(36)
  • 无人机中的坐标系、旋转矩阵与相机姿态计算

    球坐标系 球坐标系是三维坐标系中的一种,在无人机中一般使用球坐标系来表示相机姿态,相机姿态的坐标是相对于无人机的,而无人机的飞行姿态则是相对于大地坐标系的。这里我们使用的相机是2自由度的相机,即可以水平 ϕ phi ϕ 和垂直 θ theta θ 两个方向转动,其中

    2024年02月12日
    浏览(41)
  • Android之 Camera相机使用

    一 简介 1.1 随着信息时代的发展,相机在我们生活中使用越来越频繁,也成为手机的基本配置之一。相机可以用来拍照,拍视频,人脸识别,视频聊天,扫码支付,监控等常见领域 不管什么场景,基本原理都差不多,都要先通过相机采集原始数据,也就是二进制字节数据,我

    2024年02月15日
    浏览(37)
  • Unity Camera -- (2)相机投影设置

            和场景视图中的其他游戏物体一样,相机本身也可以通过使用移动和旋转工具来进行调整。但这种方式比较难用,调整起来又慢又不精确。我们可以使用Move To View功能来快速调整相机所拍摄的画面。         1. 打开Camera_Projection_Scene(Scenes目录)。         2. 在Hi

    2024年02月10日
    浏览(45)
  • 虚拟相机 Cinemachine Virtual Camera

    本质上,虚拟相机应该是 相机行为 的配置文件,虚拟相机之间的切换实际上就是在进行相机行为之间的切换; 虚拟相机并不会创建任何摄像机,他只会创建虚拟节点,实际上操作的是 Cinemachine Brain 虚拟相机属性设置完毕后,应尽量避免在游戏中对齐进行修改, 如有需要可以多创建几

    2024年02月11日
    浏览(34)
  • 【Camera2 教程二】Camera2相机打开和关闭接口调用详细说明

    上一章《Camera2教程一》里我们介绍了一些 Camera2 的基础知识,但是并没有涉及太多的 API,从本章开始我们会开发一个具有完整相机功能的应用程序,并且将相机知识分成多个篇章进行介绍,而本章所要介绍的就是相机的开启流程。 阅读本章之后,你将学会以下几个知识点:

    2024年04月25日
    浏览(36)
  • OpenCV实战(24)——相机姿态估计

    校准相机后,就可以将捕获的图像与物理世界联系起来。如果物体的 3D 结构是已知的,那么就可以预测物体如何投影到相机的传感器上,图像形成的过程由投影方程描述。当方程的大部分项已知时,就可以通过观察一些图像来推断其他元素 ( 2D 或 3D ) 的值。相机姿态估计就是

    2024年02月05日
    浏览(46)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包