homo_warping

def homo_warping(src_fea, src_proj, ref_proj, depth_values):
    # src_fea: [B, C, H, W]
    # src_proj: [B, 4, 4]
    # ref_proj: [B, 4, 4]
    # depth_values: [B, Ndepth]
    # out: [B, C, Ndepth, H, W]
    batch, channels = src_fea.shape[0], src_fea.shape[1]
    num_depth = depth_values.shape[1]
    height, width = src_fea.shape[2], src_fea.shape[3]
   with torch.no_grad():
        proj = torch.matmul(src_proj, torch.inverse(ref_proj)) # 将参考图像像素坐标映射到源图像  但是目的是要把源到参考?
        rot = proj[:, :3, :3]  # [B,3,3]
        trans = proj[:, :3, 3:4]  # [B,3,1]
        # 生成网格坐标
        y, x = torch.meshgrid([torch.arange(0, height, dtype=torch.float32, device=src_fea.device),
                               torch.arange(0, width, dtype=torch.float32, device=src_fea.device)])
        y, x = y.contiguous(), x.contiguous()
        y, x = y.view(height * width), x.view(height * width)    # 展平为height * width个元素
        xyz = torch.stack((x, y, torch.ones_like(x)))  # [3, H*W]  xyz是要得到像素坐标系(x,y,1)  [[x1...xn],[y1...yn],[1...1]],1 是齐次坐标中的常数分量
        xyz = torch.unsqueeze(xyz, 0).repeat(batch, 1, 1)  # [B, 3, H*W]  # 在指定维度 dim 插入一个新的维度
        rot_xyz = torch.matmul(rot, xyz)  # [B, 3, H*W]
        rot_depth_xyz = rot_xyz.unsqueeze(2).repeat(1, 1, num_depth, 1) * depth_values.view(batch, 1, num_depth,
                                                                                            1)  # [B, 3, Ndepth, H*W]  对于每个深度值的三维坐标。这个操作通过将深度值应用于旋转后的坐标,得到每个深度层的三维坐标
        proj_xyz = rot_depth_xyz + trans.view(batch, 3, 1, 1)  # [B, 3, Ndepth, H*W] 将旋转和位移应用到三维坐标上的结果,得到的是每个深度值的三维坐标
        proj_xy = proj_xyz[:, :2, :, :] / proj_xyz[:, 2:3, :, :]   # [B, 2, Ndepth, H*W]  将 proj_xyz 的前三维(x 和 y)除以第三维(z)来将三维坐标投影到二维平面上。
        proj_x_normalized = proj_xy[:, 0, :, :] / ((width - 1) / 2) - 1
        proj_y_normalized = proj_xy[:, 1, :, :] / ((height - 1) / 2) - 1
        proj_xy = torch.stack((proj_x_normalized, proj_y_normalized), dim=3)  # [B, Ndepth, H*W, 2]
        grid = proj_xy
    # grid 是一个采样网络,例如grid(0,0)表示输出图像的第一个像素是输入图像【1.5,1.5】位置的像素,实际上这个位置的像素值由插值算出来
    # grid = [[[1.5, 1.5], [2.5, 2.5]], // 第一行输出的两个像素位置
    #          [[1.5, 1.5], [2.5, 2.5]]] // 第二行输出的两个像素位置

    warped_src_fea = F.grid_sample(src_fea, grid.view(batch, num_depth * height, width, 2), mode='bilinear',
                                   padding_mode='zeros')
    warped_src_fea = warped_src_fea.view(batch, channels, num_depth, height, width)

    return warped_src_fea`

这个函数 homo_warping 的主要作用是将源图像特征 src_fea 根据参考图像的视角和一系列深度值进行重投影,生成多视角几何中的特征对齐。具体来说,该函数通过利用投影矩阵和深度值,将源图像的特征图投影到参考图像的视角下,并进行双线性插值,得到在不同深度值下的重投影特征图。

函数输入

  • src_fea: 源图像特征图,形状为 [B, C, H, W],其中 B 是批次大小,C 是通道数,HW 分别是高度和宽度。
  • src_proj: 源图像的投影矩阵,形状为 [B, 4, 4]
  • ref_proj: 参考图像的投影矩阵,形状为 [B, 4, 4]
  • depth_values: 深度值数组,形状为 [B, Ndepth],其中 Ndepth 是深度值的数量。

函数输出

  • warped_src_fea: 重投影后的源图像特征图,形状为 [B, C, Ndepth, H, W]

函数步骤

  1. 初始化和形状提取

    • 提取输入特征图的批次大小、通道数、深度值数量、高度和宽度。
  2. 计算相对投影矩阵

    • 通过矩阵乘法 torch.matmul(src_proj, torch.inverse(ref_proj)) 计算源图像和参考图像之间的相对投影矩阵。
    • 提取旋转矩阵 rot 和平移向量 trans
  3. 生成像素网格坐标

    • 使用 torch.meshgrid 生成源图像平面的 xy 坐标网格。
    • 将坐标展平并堆叠为 [3, H*W] 的张量,表示齐次坐标系中的像素坐标 [x, y, 1]
    • 扩展批次维度并重复,以得到 [B, 3, H*W] 的坐标张量。
  4. 应用旋转和深度

    • 将旋转矩阵 rot 应用于像素坐标,得到旋转后的坐标 rot_xyz
    • 将深度值应用于旋转后的坐标,得到每个深度层的三维坐标 rot_depth_xyz
  5. 应用投影和归一化

    • 将平移向量 trans 应用于三维坐标,得到投影后的三维坐标 proj_xyz
    • 将三维坐标投影到二维平面,得到 proj_xy
    • 归一化 proj_xy,使其坐标范围在 [-1, 1] 之间,以适应 grid_sample 函数的要求。
  6. 生成网格并采样

    • 使用 proj_xy 生成采样网格 grid
    • 使用 F.grid_sample 函数根据采样网格从源图像特征图 src_fea 中进行双线性插值,生成重投影后的特征图 warped_src_fea
  7. 调整输出形状

    • 将重投影后的特征图 warped_src_fea 的形状调整为 [B, C, Ndepth, H, W]

总结

这个函数通过将源图像的特征图根据参考图像的视角和一系列深度值进行重投影,实现了多视角几何中的特征对齐。这样可以在不同的深度层上对源图像的特征进行采样,生成在参考视角下的特征图,用于后续的深度估计或三维重建等任务。

  • 4
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ocpro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值