14、SynSin:单图像端到端视图合成技术详解

SynSin单图像视图合成解析

SynSin:单图像端到端视图合成技术详解

1. 视图合成方法概述

在视图合成领域,面临着诸多挑战,尤其是模型难以从图像中理解 3D 场景。目前主要有以下几种视图合成方法:
- 多图像视图合成 :利用深度神经网络学习多幅图像的深度信息,进而从不同视角重建新图像。不过,这需要获取来自略微不同视角的多幅图像,有时获取这类数据颇具难度。
- 基于真实深度的视图合成 :该方法除了图像外,还使用代表图像深度和语义的真实掩码。尽管在某些情况下,这类模型能取得不错的效果,但大规模收集数据既困难又昂贵,特别是针对户外场景。而且,大规模标注此类数据也耗时费力。
- 单图像视图合成 :这是一种更为现实的场景,即仅拥有一幅图像,却要从新视角重建图像。仅依靠单幅图像获取更精确的结果难度较大。SynSin 就属于能够实现先进视图合成的方法之一。

2. SynSin 网络架构

SynSin 的核心思想是借助端到端模型,仅在测试时使用单幅图像来解决视图合成问题。该模型无需 3D 数据标注,且与基线模型相比,能达到很高的精度。其端到端训练的模型由以下三个不同模块组成:
- 空间特征和深度网络
- 神经点云渲染器
- 细化模块和判别器

下面我们深入了解每个模块。

2.1 空间特征和深度网络

此模块由空间特征网络(f)和深度网络(d)构成,二者均以同一幅参考图像作为输入。
- 空间特征网络 :旨在学习特征图,这些特征图是图像的高分辨率表示,负责学习图像的语义信息。该模型由八个 ResNet 块组成,为图像的每个像素输出 64 维特征图,输出分辨率与原始图像相同。
- 深度网络 :致力于学习图像的 3D 结构。由于未使用精确的 3D 标注,其学习到的 3D 结构并非十分精确,但模型会进一步优化。该网络采用具有八个下采样和上采样层的 UNet,随后是 sigmoid 层,输出分辨率同样与原始图像一致。

这两个模型的输出通道都保持高分辨率,有助于重建更精确、更高质量的图像。

2.2 神经点云渲染器

该模块的主要任务是创建 3D 点云,以便通过视图变换点从新视角渲染新图像。它利用空间特征和深度网络的组合输出。

在大多数情况下,会使用简单渲染器将 3D 点投影到新视图的一个像素或小区域。然而,简单渲染器存在问题:它不可微,无法使用梯度更新深度和空间特征网络;并且我们希望渲染特征而非 RGB 图像,因此简单渲染器不适用于此技术。

为解决这些问题,采用了神经点云渲染器。它不直接为点分配像素,而是以不同的影响力进行散点处理,解决了小邻域问题;对于硬 z - 缓冲区问题,它会累积最近点的影响,而非仅考虑最近的一个点。

具体操作如下:
1. 3D 点以半径 r 进行投影和散点处理,通过散点中心点到该点的欧几里得距离来衡量 3D 点对该像素的影响。
2. 对 z - 缓冲区中的点进行排序,根据点到新相机的距离排序,然后使用 K 近邻和 alpha 合成来累积点,最终输出未细化的新视图,作为细化模块的输入。

神经点云渲染器的优势在于能为一个 3D 点收集更多梯度,提升空间特征和深度网络的学习过程。

2.3 细化模块和判别器

细化模块有两个主要任务:一是提高投影特征的准确性,二是填充新视图中图像的不可见部分,输出语义有意义且几何精确的图像。例如,若图像中仅可见桌子的一部分,在新视图中应包含桌子更大的部分,该模块需从语义上理解这是桌子,并在重建过程中保证新部分的线条几何正确。

该模块使用生成模型,采用具有八个块的 ResNet,并使用下采样和上采样块以保持图像分辨率。同时,使用带有两个多层判别器的 GAN 和判别器上的特征匹配损失。模型的最终损失由生成图像与目标图像之间的 L1 损失、内容损失和判别器损失组成,用于模型优化。

3. 模型训练和测试实践

Facebook Research 发布了 SynSin 模型的 GitHub 仓库,方便我们进行模型训练和使用预训练模型进行推理。以下是具体的操作步骤:

3.1 模型设置
git clone https://github.com/facebookresearch/synsin.git
cd synsin/
conda create --name synsin_env --file requirements.txt
conda activate synsin_env

若上述命令无法安装所需依赖,可按照 synsin/INSTALL.md 文件中的说明手动安装。

3.2 数据集选择与下载

模型在三个不同的数据集上进行训练:
- RealEstate10K
- MP3D
- KITTI

这里以 KITTI 数据集为例,可从数据集网站下载数据。具体操作如下:
1. 从网站下载 KITTI 数据集,并将文件存储在 ${KITTI_HOME}/dataset_kitti 中,其中 KITTI_HOME 是数据集的存储路径。
2. 更新 ./options/options.py 文件,添加本地 KITTI 数据集的路径:

elif opt.dataset == 'kitti':
    opt.min_z = 1.0
    opt.max_z = 50.0
    opt.train_data_path = (
        './DATA/dataset_kitti/'
    )
    from data.kitti import KITTIDataLoader
    return KITTIDataLoader

若使用其他数据集,需找到对应数据集的 DataLoader 并添加数据集路径。

3.3 下载预训练模型
bash ./download_models.sh

此命令会为三个数据集创建不同的文件夹,并下载所有预训练模型,可用于训练和推理。若不想下载所有预训练模型,可手动运行以下命令:

wget https://dl.fbaipublicfiles.com/synsin/checkpoints/realestate/synsin.pth

还可下载 readme.txt 文件获取更多预训练模型信息:

wget https://dl.fbaipublicfiles.com/synsin/checkpoints/readme.txt
3.4 模型训练

运行 train.py 文件进行训练,可通过 ./train.sh 脚本执行。以 KITTI 数据集为例,默认命令如下:

python train.py --batch-size 32 \
    --folder 'temp' --num_workers 4 \
    --resume --dataset 'kitti' --use_inv_z \
    --use_inverse_depth \
    --accumulation 'alphacomposite' \
    --model_type 'zbuffer_pts' \
    --refine_model_type 'resnet_256W8UpDown64' \
    --norm_G 'sync:spectral_batch' \
    --gpu_ids 0,1 --render_ids 1 \
    --suffix '' --normalize_image --lr 0.0001

训练完成后,可使用新模型进行评估。

3.5 模型评估
  1. 生成地面真值图像:
export KITTI=${KITTI_HOME}/dataset_kitti/images
python evaluation/eval_kitti.py --old_model ${OLD_MODEL} --result_folder ${TEST_FOLDER}

需将 ${TEST_FOLDER} 替换为结果保存路径。此脚本会为每个图像创建生成图像和地面真值图像对。
2. 计算评估指标:

python evaluation/evaluate_perceptualsim.py \
    --folder ${TEST_FOLDER} \
    --pred_image im_B.png \
    --target_image im_res.png \
    --output_file kitti_results

该命令会根据测试图像路径评估模型,输出感知相似度、PSNR 和 SSIM 等指标。感知相似度衡量图像在 VGG 特征空间中的距离,越接近 0 表示图像相似度越高;PSNR 计算最大信号功率与失真噪声功率之比;SSIM 量化图像质量的下降程度。

4. 使用预训练模型进行推理

以下是使用预训练模型进行推理的具体步骤:

4.1 导入必要的包
import torch
import torch.nn as nn
import sys
sys.path.insert(0, './synsin')
import os
os.environ['DEBUG'] = '0'
from synsin.models.networks.sync_batchnorm import convert_model
from synsin.models.base_model import BaseModel
from synsin.options.options import get_model
4.2 创建推理模型
def synsin_model(model_path):
    torch.backends.cudnn.enabled = True
    opts = torch.load(model_path)['opts']
    opts.render_ids = [1]
    torch_devices = [int(gpu_id.strip()) for gpu_id in opts.gpu_ids.split(",")]
    device = 'cuda:' + str(torch_devices[0])

    model = get_model(opts)
    if 'sync' in opts.norm_G:
        model = convert_model(model)
    model = nn.DataParallel(model, torch_devices[0:1]).cuda()

    model_to_test = BaseModel(model, opts)
    model_to_test.load_state_dict(torch.load(model_path)['state_dict'])
    model_to_test.eval()
    print("Loaded model")
    return model_to_test
4.3 推理代码示例
import matplotlib.pyplot as plt
import quaternion
import torch
import torch.nn as nn
import torchvision.transforms as transforms
from PIL import Image
from set_up_model_for_inference import synsin_model

def inference(model_path, test_image, theta=-0.15, phi=-0.1, tx=0, ty=0, tz=0.1, save_path=None):
    model_to_test = synsin_model(model_path)
    transform = transforms.Compose([
        transforms.Resize((256, 256)),
        transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
    ])
    if isinstance(test_image, str):
        im = Image.open(test_image)
    else:
        im = test_image
    im = transform(im)

    RT = torch.eye(4).unsqueeze(0)
    RT[0, 0:3, 0:3] = torch.Tensor(quaternion.as_rotation_matrix(quaternion.from_rotation_vector([phi, theta, 0])))
    RT[0, 0:3, 3] = torch.Tensor([tx, ty, tz])

    batch = {
        'images': [im.unsqueeze(0)],
        'cameras': [
            {
                'K': torch.eye(4).unsqueeze(0),
                'Kinv': torch.eye(4).unsqueeze(0)
            }
        ]
    }

    with torch.no_grad():
        pred_imgs = model_to_test.model.module.forward_angle(batch, [RT])
        depth = nn.Sigmoid()(model_to_test.model.module.pts_regressor(batch['images'][0].cuda()))

    fig, axis = plt.subplots(1, 3, figsize=(10, 20))
    axis[0].axis('off')
    axis[1].axis('off')
    axis[2].axis('off')
    axis[0].imshow(im.permute(1, 2, 0) * 0.5 + 0.5)
    axis[0].set_title('Input Image')
    axis[1].imshow(pred_imgs[0].squeeze().cpu().permute(1, 2, 0).numpy() * 0.5 + 0.5)
    axis[1].set_title('Generated Image')
    axis[2].imshow(depth.squeeze().cpu().clamp(max=0.04))
    axis[2].set_title('Predicted Depth')

    if save_path:
        plt.savefig(save_path)
    return pred_imgs[0].squeeze().cpu().permute(1, 2, 0).numpy()

4.4 连续图像生成与视频制作
from inference_unseen_image import inference
from PIL import Image
import numpy as np
import imageio

def create_gif(model_path, image_path, save_path, theta=-0.15, phi=-0.1, tx=0, ty=0, tz=0.1, num_of_frames = 5):
    im = inference(model_path, test_image=image_path, theta=theta, phi=phi, tx=tx, ty=ty, tz=tz)
    frames = []
    for i in range(num_of_frames):
        im = Image.fromarray((im * 255).astype(np.uint8))
        frames.append(im)
        im = inference(model_path, im, theta=theta, phi=phi, tx=tx, ty=ty, tz=tz)
    imageio.mimsave(save_path, frames, duration=1)

通过以上步骤,我们可以详细了解 SynSin 网络架构、训练过程、评估方法以及如何使用预训练模型进行推理和连续图像生成。在实际应用中,可以尝试调整模型的超参数、不同的相机设置和步长,以提高或降低模型输出的准确性。

SynSin:单图像端到端视图合成技术详解

5. 技术要点总结与分析

为了更清晰地理解 SynSin 技术,我们对前面介绍的内容进行总结和分析,以下是关键技术点的表格梳理:
| 模块名称 | 主要功能 | 技术实现 | 优势 |
| — | — | — | — |
| 空间特征和深度网络 | 学习图像语义信息和 3D 结构 | 空间特征网络用八个 ResNet 块输出 64 维特征图;深度网络用 UNet 加 sigmoid 层 | 输出高分辨率特征,利于重建高质量图像 |
| 神经点云渲染器 | 创建 3D 点云并从新视角渲染图像 | 散点处理解决小邻域问题,累积最近点影响解决硬 z - 缓冲区问题 | 为 3D 点收集更多梯度,提升网络学习效果 |
| 细化模块和判别器 | 提高投影特征准确性,填充图像不可见部分 | 使用生成模型(八个块的 ResNet),结合 GAN 和特征匹配损失 | 输出语义和几何精确的图像 |

同时,我们可以用 mermaid 流程图展示 SynSin 模型的整体工作流程:

graph LR
    A[输入参考图像] --> B[空间特征和深度网络]
    B --> C[神经点云渲染器]
    C --> D[细化模块和判别器]
    D --> E[输出新视角图像]
6. 常见问题及解决方案

在使用 SynSin 模型进行训练和推理过程中,可能会遇到一些常见问题,以下为你提供相应的解决方案:
- 依赖安装问题 :在使用 conda create --name synsin_env --file requirements.txt 命令安装依赖时,可能会出现安装失败的情况。此时可按照 synsin/INSTALL.md 文件中的说明手动安装依赖。
- 数据集路径问题 :如果在更新 ./options/options.py 文件时,没有正确添加数据集路径,会导致模型无法找到数据。需要仔细检查路径是否正确,确保路径指向本地数据集的存储位置。
- 模型加载问题 :在加载预训练模型时,可能会因为文件损坏或路径错误而失败。可以检查文件是否完整,路径是否正确,也可以手动下载预训练模型。
- 推理结果不佳问题 :如果推理得到的新视角图像质量不佳,可能是由于超参数设置不合理、相机参数不合适或步长过大等原因。可以尝试调整模型的超参数、不同的相机设置和步长,观察结果的变化。

7. 拓展应用与未来展望

SynSin 模型在视图合成领域具有很大的应用潜力,以下是一些可能的拓展应用场景:
- 虚拟现实(VR)和增强现实(AR) :在 VR 和 AR 应用中,需要实时生成不同视角的图像,SynSin 模型可以根据用户的视角变化,快速生成高质量的新视角图像,增强用户的沉浸感。
- 自动驾驶 :在自动驾驶场景中,车辆需要获取周围环境的不同视角信息,SynSin 模型可以利用单幅图像生成多个视角的图像,帮助车辆更好地感知周围环境,提高驾驶安全性。
- 影视制作 :在影视制作中,常常需要制作一些特效场景,SynSin 模型可以根据已有的图像生成不同视角的图像,为特效制作提供更多的素材和可能性。

未来,随着技术的不断发展,SynSin 模型可能会在以下方面得到进一步的优化和改进:
- 提高模型的准确性和效率 :通过改进网络架构、优化算法等方式,提高模型生成新视角图像的准确性和效率,减少计算时间和资源消耗。
- 支持更多类型的数据集 :目前模型主要在 RealEstate10K、MP3D 和 KITTI 等数据集上进行训练,未来可以尝试在更多类型的数据集上进行训练,提高模型的泛化能力。
- 与其他技术的融合 :将 SynSin 模型与其他计算机视觉技术,如目标检测、语义分割等相结合,实现更复杂的任务和应用。

8. 总结

SynSin 是一种强大的单图像端到端视图合成模型,通过空间特征和深度网络、神经点云渲染器以及细化模块和判别器的协同工作,能够从单幅图像中生成高质量的新视角图像。本文详细介绍了 SynSin 模型的网络架构、训练过程、评估方法以及推理步骤,并提供了相应的代码示例。同时,还对模型的技术要点进行了总结和分析,探讨了常见问题及解决方案,以及拓展应用和未来展望。希望本文能够帮助你更好地理解和应用 SynSin 模型,在视图合成领域取得更好的成果。在实际应用中,你可以根据具体需求调整模型的超参数和设置,不断探索和尝试,挖掘 SynSin 模型的更多潜力。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值