PyTorch3D 立体隐式形状渲染:教你构建场景 3D 结构
內容導讀
3D 深度學習一直是機器視覺領域的難點,為了準確高效地建立場景的立體模型,得到相對真實的渲染成果,行業內的一些大廠先后開源了自己的研發成果。
本文首發自微信公眾號「PyTorch 開發者社區」
隨著計算機視覺領域相關技術的發展,針對 2D 圖像的處理效率和精度得到了顯著地提升。
但是現實環境中,物體多以 3D 立體結構的形式存在,如何準確地提升 AI 系統對復雜現實環境的感知和理解能力,正確處理 3D 圖像, 正在成為日趨關鍵的技術難點。
2019 年 Facebook AI 發布 Mesh R-CNN 模型進行 3D 目標檢測與形狀預測
2020 年 1 月 23 日,Facebook AI 發布了 PyTorch3D v0.1.0 版本。PyTorch3D 是 PyTorch 中經過優化的、高效、可重用組件庫,它具有 3 大突出特點:高效、模塊化和可微分,旨在簡化在 PyTorch 中進行 3D 深度學習的難度。
PyTorch3D 中提供了 3D 算子和渲染兩大組件。
在 3D 算子中,Fit Mesh 可以利用 3D 損失函數,把初始的通用形狀變形為目標形狀,并借助一些規則讓目標形狀變得更為流暢。 而 3D 算子中的光束平差法(Bundle Adjustment),則提供了 cameras、transforms、so3 共計 3 個 API,根據給定相機的視角,形成對照相機視角的映射,從而推斷場景的 3D 結構。
渲染則包括紋理網格渲染器(Render Textured Meshes)、DensePose 網格渲染器(Render DensePose Meshed)、彩色點云渲染器(Render Colored Pointclouds)等, 借助這些渲染器,可以進一步優化形成的場景 3D 結構。
2020 年 2 月 6 日,PyTorch3D 相關代碼在 GitHub 開源。經過 5 個版本的迭代后,2021 年 2 月 9 日,PyTorch3D 發布第 6 個公開版本 v0.4.0,** 新增隱函數、立體渲染和 NeRF 重新實現等功能,**為 3D 深度學習研究提供了更迅速、更靈活的開源庫。
圖為 PyTorch3D logo,由 PyTorch3D 的隱式立體渲染器生成的
隱式形狀渲染(Implicit Shape Rendering)
隱式形狀渲染是指基于輸入場景的新視角,生成 3D 場景的真實渲染,其核心思想是利用神經網絡與可微分渲染,重建 3D 場景表面的隱式形態, 這使得僅依靠 2D 視圖就可以學習 3D 場景中的幾何形狀。
進行隱式形狀渲染需要幾個關鍵組件,包括數據卷的抽象類(abstraction for volume data)以及可微分的隱式形狀渲染器。
為了讓行業從業者更容易地針對隱式形狀渲染進行嘗試,PyTorch3D 已經為用戶提供了一系列常用的 3D 算子(3D operators)和損失函數,以及一個模塊化、可微分的渲染 API。 在指出核心可重用組件的同時,也提供了這些組件經驗證的、標準化實現方法。
在 PyTorch3D v0.4.0 中,包括 5 個支持隱式形狀渲染的新特性:
1、新增數據卷結構(Volumes data structure),支持 3D 卷的批處理和坐標框架之間的轉換;
2、新增多個光線紋理實現方法:
GridRaysampler
MonteCarloRaysampler
NDCGridRaysampler
3、新增多個 Raymarcher 實現方法:
AbsorptionOnlyRaymarcher
EmissionAbsorptionRaymarcher
4、新增隱式渲染器(ImplicitRenderer)和體積渲染器(VolumeRenderer)API,構成 Raysampler 和 Raymarcher
5、新增多個效用函數,如點云到體積的可微分轉換。
利用 PyTorch3D 生成的甜甜圈 3D 圖像
要使用這些新組件,可以借助一個模塊化、文檔完備的 NeRF 重新實現。
NeRF 是一個深度學習模型, 由 Google Research 團隊開發,旨在借助神經輻射場(Neural Radiance Fields)表示場景,從而進行視圖合成(View Synthesis)。
NeRF 僅使用非結構化圖像集合,就能合成復雜的 3D 場景圖。
而改良版的 NeRF 重新實現,性能得到了極大提升,在保證輸出圖像質量的同時,比正式版本運行得更快。
使用 PyTorch3D 的 NeRF 重新實現功能,生成了形狀和光影復雜的 3D 圖像示例
教程(Fit Textured Volume)
我們基于 PyTorch3D GitHub 官方教程 Fit Textured Volume,進行了漢化和整理,演示如何在 PyTorch3D 中,利用可微分立體渲染,依據給定場景的一組視圖,預測場景的立體結構。
用 Raymarching 構建場景 3D 立體結構
本教程將介紹:
- 如何創建一個可微分的立體渲染器;
- 如何創建一個立體模型(包括如何使用 Volumes 類);
- 使用可微分的立體渲染器,根據圖像擬合立體結構;
- 將預測的立體結構可視化。
備注:限于篇幅有限,本文僅展示部分代碼,完整代碼請移步:
https://openbayes.com/console/openbayes/containers/oAYzp70wwPk/overview
0. 安裝和導入模塊
確保已安裝 torch 和 torchvision 。
如果沒有安裝 pytorch3d ,請使用以下代碼安裝。
1. 生成場景及 mask 的圖像
以下代碼將生成本次訓練數據。它會通過 fit_textured_mesh.ipynb 教程,從多個角度渲染奶牛圖像,并返回以下內容:
一系列由奶牛網格渲染器生成的圖像及其剪影的張量;與所有攝像機鏡頭一一對應的渲染器。
備注:在 generate_cow_renders 函數中實現網格渲染的工作原理請參考:
fit_textured_mesh.ipynb
2. 初始化體積渲染器
初始化體積渲染器會從目標圖像的每個像素發出一條射線,并沿射線采樣一組間隔均勻的點。與每個射線點相對應的密度值和色值,可通過查詢場景的體積模型中的相應位置獲得。
渲染器由一個 raymarcher 和一個 raysampler 構成。
raysampler 負責從圖像像素中發射射線,并沿著射線對點進行取樣。此處使用的是 NDCGridRaysampler ,它符合標準的 PyTorch3D 坐標網格規范。
raymarcher 獲得射線采樣的密度和顏色,并將所有射線渲染成光線源像素的顏色和不透明度值。此處使用的是 EmissionAbsorptionRaymarcher ,它實現了標準的 Emission-Absorption Raymarching 算法。
# render_size 表示渲染圖像各個邊的像素大小,將其設置為與目標圖像尺寸一致 # 也就是說將其渲染成與基準圖像一樣的尺寸 render_size = target_images.shape[1]# 渲染場景以(0,0,0)為中心,被限定在一個邊長約等于 3.0 (國際單位)的邊框內。 volume_extent_world = 3.0# 1) 實例化 raysampler # 此處 NDCGridRaysampler 會生成一矩形圖像網格的射線,其坐標遵循 pytorch3d 坐標規定 # 由于此處設定的體積是 128^3,因此取樣 n_pts_per_ray=150 # 大致相當于每個體素都有一個射線點 # 進一步設置 min_depth=0.1,因為相機平面內的所有表面都超過了 0.1 單位 raysampler = NDCGridRaysampler(image_width=render_size,image_height=render_size,n_pts_per_ray=150,min_depth=0.1,max_depth=volume_extent_world, )# 2) 實例化 raymarcher. # 此處用的是標準 EmissionAbsorptionRaymarcher # 它會沿著每條射線前進 # 將每條射線都渲染成一個單一的 3D 顏色向量和一個不透明度標量 raymarcher = EmissionAbsorptionRaymarcher()# 最后,用 raysampler 和 raymarcher 實例化體積渲染器 renderer = VolumeRenderer(raysampler=raysampler, raymarcher=raymarcher, )3. 初始化體積模型
接下來實例化場景的體積模型。這會使得 3D 空間量化為體積像素,其中每個體素都用體素 RGB 顏色的 3D 向量,和描述體素不透明度的密度標量(范圍在[0-1]之間,數字越大不透明越高)來表示。
為了保證密度和顏色的取值范圍在 [0-1] 之間,我們會在對數空間中表示體積顏色和密度。模型運行 forward 函數時, log-space 值會通過 sigmoid 函數傳遞,從而使得 log-space 值處于正確的取值范圍。
此外, VolumeModel 還包含渲染器對象。這個對象在整個優化過程中保持不變。
本部分代碼還定義了 huber 損失函數,它可以計算出渲染色和 mask 之間的差異。
4. 體積擬合
這一步,我們用可微分渲染來進行體積擬合。
為了擬合體積,我們從 target_camera 的視角進行渲染,并將渲染結果與觀察到的 target_images 和 target_silhouettes 進行對比。
這種對比是通過評估的 target_images/rendered_images 和 target_silhouettes/rendered_silhouettes 之間的平均 huber(smooth-l1)誤差來完成的。
5. 將優化后的場景體積進行可視化
最后,旋轉場景體積的 y 軸,從多個視點進行渲染,將優化后的體積進行可視化。
def generate_rotating_volume(volume_model, n_frames = 50):logRs = torch.zeros(n_frames, 3, device=device)logRs[:, 1] = torch.linspace(0.0, 2.0 * 3.14, n_frames, device=device)Rs = so3_exponential_map(logRs)Ts = torch.zeros(n_frames, 3, device=device)Ts[:, 2] = 2.7frames = []print('Generating rotating volume ...')for R, T in zip(tqdm(Rs), Ts):camera = FoVPerspectiveCameras(R=R[None], T=T[None], znear = target_cameras.znear[0],zfar = target_cameras.zfar[0],aspect_ratio = target_cameras.aspect_ratio[0],fov = target_cameras.fov[0],device=device,)frames.append(volume_model(camera)[..., :3].clamp(0.0, 1.0))return torch.cat(frames)with torch.no_grad():rotating_volume_frames = generate_rotating_volume(volume_model, n_frames=7*4)image_grid(rotating_volume_frames.clamp(0., 1.).cpu().numpy(), rows=4, cols=7, rgb=True, fill=True) plt.show()6. 結論
本教程中演示了如何優化場景的 3D 立體構造,使已知視點的體積渲染與每個視點的觀測圖像相匹配。
教程中的渲染是使用 NDCGridRaysampler 和 EmissionAbsorptionRaymarcher 構成的 PyTorch3D 立體渲染器完成的。
為 2D 圖像構建有紋理的立體形狀
完整教程請查看: https://openbayes.com/console/openbayes/containers/oAYzp70wwPk/overview
參考:
https://ai.facebook.com/blog/-introducing-pytorch3d-an-open-source-library-for-3d-deep-learning/
https://github.com/facebookresearch/pytorch3d
總結
以上是生活随笔為你收集整理的PyTorch3D 立体隐式形状渲染:教你构建场景 3D 结构的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 配有N显卡的i系列CPU笔记本Media
- 下一篇: 【贴吧顶贴教学】10分钟快速解锁顶贴软件