<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Conputer Graphics on NCJ Tech Blog</title>
    <link>https://blog.chong-zeng.com/tags/conputer-graphics/</link>
    <description>Recent content in Conputer Graphics on NCJ Tech Blog</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Tue, 15 Feb 2022 00:00:00 +0000</lastBuildDate>
    <atom:link href="https://blog.chong-zeng.com/tags/conputer-graphics/rss.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>[Paper Reading] RXMesh: A GPU Mesh Data Structure</title>
      <link>https://blog.chong-zeng.com/posts/2022-02-15_rxmesh/</link>
      <pubDate>Tue, 15 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-02-15_rxmesh/</guid>
      <description>1. 这篇文章究竟讲了什么问题？ 如何利用 GPU 来并行加速大规模的网格处理
2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？ 属于改进类的问题
以往的网格加速方法要么是：
application-specific 需要从线性代数上对问题进行 reform mesh 会变为稀疏矩阵 减少了中间变量，但是局部性变差，性能不够好 所以需要一个通用的高性能加速框架
3. 这篇文章致力于证明什么假设？ 通过高效的数据结构 + 更好的变成模型，可以实现通用的网格处理加速
4. 有哪些与这篇文章相关的研究？ 高性能编程模型 图像处理：Halide，调度与算法分离 稀疏体素计算 / simulation：太极 纯模拟：Ebb 图处理：Gunrock 5. 这篇文章提出的问题解决方案中，核心贡献是什么？ 一个 high-level 的编程模型
用户顶层 定义好每个 mesh 上执行的计算
八种查询
以计算 vertex normal 为例：
非常清晰
模型底层 通过将整个 mesh 切分成很多 patch，然后按照 patch 来往 GPU 的 block 上分配计算任务，进而增加了局部性
patching 之后的 index 可视化出来如下图，很明显，比起直接按照 global sorting 的划分，patching 下相同 index 的部分会更加集中，相关数据在查询、计算的时候可以常驻 shared memory
那么 patch 如何表示？</description>
      <content:encoded><![CDATA[<h1 id="1-这篇文章究竟讲了什么问题">1. 这篇文章究竟讲了什么问题？</h1>
<p>如何利用 GPU 来并行加速大规模的网格处理</p>
<h1 id="2-这个问题的性质是什么如果不完全是一个新问题那为什么它仍然重要">2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？</h1>
<p>属于改进类的问题</p>
<p>以往的网格加速方法要么是：</p>
<ol>
<li>application-specific</li>
<li>需要从线性代数上对问题进行 reform
<ol>
<li>mesh 会变为稀疏矩阵</li>
<li>减少了中间变量，但是局部性变差，性能不够好</li>
</ol>
</li>
</ol>
<p>所以需要一个通用的高性能加速框架</p>
<h1 id="3-这篇文章致力于证明什么假设">3. 这篇文章致力于证明什么假设？</h1>
<p>通过高效的数据结构 + 更好的变成模型，可以实现通用的网格处理加速</p>
<h1 id="4-有哪些与这篇文章相关的研究">4. 有哪些与这篇文章相关的研究？</h1>
<ol>
<li>高性能编程模型
<ol>
<li>图像处理：Halide，调度与算法分离</li>
<li>稀疏体素计算 / simulation：太极</li>
<li>纯模拟：Ebb</li>
<li>图处理：Gunrock</li>
</ol>
</li>
</ol>
<h1 id="5-这篇文章提出的问题解决方案中核心贡献是什么">5. 这篇文章提出的问题解决方案中，核心贡献是什么？</h1>
<p>一个 high-level 的编程模型</p>
<h2 id="用户顶层">用户顶层</h2>
<ol>
<li>
<p>定义好每个 mesh 上执行的计算</p>
</li>
<li>
<p>八种查询</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/0.png" alt="Untitled"  />
</p>
</li>
<li>
<p>以计算 vertex normal 为例：</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/1.png" alt="Untitled"  />
</p>
<p>非常清晰</p>
</li>
</ol>
<h2 id="模型底层">模型底层</h2>
<ol>
<li>
<p>通过将整个 mesh 切分成很多 patch，然后按照 patch 来往 GPU 的 block 上分配计算任务，进而增加了局部性</p>
<p>patching 之后的 index 可视化出来如下图，很明显，比起直接按照 global sorting 的划分，patching 下相同 index 的部分会更加集中，相关数据在查询、计算的时候可以常驻 shared memory</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/2.png" alt="Untitled"  />
</p>
</li>
<li>
<p>那么 patch 如何表示？</p>
<p>作者选用了 LAR (Linear Algebraic Representation) 来表示每个 patch</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/3.png" alt="Untitled"  />
</p>
<p>这样的表示更加紧凑</p>
<ul>
<li>另外因为每个 patch 其实不大，所以每个 patch 内的信息都可以使用 16-bit 来表示，使得数据更加紧凑</li>
</ul>
</li>
<li>
<p>负载均衡</p>
<p>设计了类似任务队列的机制，block 内的 thread 不与 vertex 绑定，而是采用协作的模式，使得各个 thread 的负载较为均匀</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/4.png" alt="Untitled"  />
</p>
</li>
<li>
<p>ribbon 机制</p>
<p>为了减少 block 之间的通信开销，每个 patch 会额外增加边上的一圈网格，从而无需从其他 patch 取计算结果</p>
<p><img loading="lazy" src="/2022-02-15_RXMesh.assets/5.png" alt="Untitled"  />
</p>
</li>
</ol>
<h1 id="6-实验是如何设计的">6. 实验是如何设计的？</h1>
<ol>
<li>查询操作（对比通用性能）
<ol>
<li>与 PDE、OpenMesh、CGAL 等业界库对比性能</li>
</ol>
</li>
<li>应用（对比特定应用性能）
<ol>
<li>Mean Curvature Flow</li>
<li>Geodesic Distance</li>
<li>Bilateral Filtering</li>
<li>Vertex Normal</li>
</ol>
</li>
</ol>
<h1 id="7-实验是在什么样的数据集基础上运行的">7. 实验是在什么样的数据集基础上运行的？</h1>
<p>网格取自 Thingi10K: A Dataset of 10,000 3D-Printing Models</p>
<h1 id="8-实验结果能否有力地支持假设">8. 实验结果能否有力地支持假设？</h1>
<ol>
<li>通用查询
<ol>
<li>速度吊打 OpenMesh 和 CGAL</li>
<li>一些场景比 PDE 略慢
<ol>
<li>比如 EV、EF 的时候，因为 PDE 只需要写 4-bytes per-thread，所以快不少</li>
</ol>
</li>
</ol>
</li>
<li>特定应用
<ol>
<li>Mean Curvature Flow
<ol>
<li>4.6x faster than PDE</li>
</ol>
</li>
<li>Geodesic Distance
<ol>
<li>15.5x faster than PDE</li>
</ol>
</li>
<li>Bilateral Filtering
<ol>
<li>因为 RXMesh 需要读 ribbon，多读了</li>
<li>PDE 比 RXMesh 快 1.12x</li>
</ol>
</li>
<li>Vertex Normal
<ol>
<li>hardwired Indexed triangle 比 RXMesh 快 1.14x</li>
<li>因为 Mesh Matrix / hardwired version 的内存更加规整
<ol>
<li>每个面只读三个顶点，一点都不多读</li>
</ol>
</li>
<li>即便如此，RXMesh 速度还是不错的，毕竟写起来简单多了而且是通用方法</li>
</ol>
</li>
</ol>
</li>
<li>两组实验都充分表明了 RXMesh 的优越</li>
</ol>
<h1 id="9-这篇文章的贡献是什么">9. 这篇文章的贡献是什么？</h1>
<p>一个通用的、高性能的、高级的网格数据处理编程模型</p>
<blockquote>
<p>作者在 slide 里补充了一句作为结论：
Programmer-managed caching is the right way to capture mesh locality and improve GPU performance for mesh processing</p>
</blockquote>
<h1 id="10-下一步可以做什么">10. 下一步可以做什么？</h1>
<ol>
<li>支持动态网格
<ol>
<li>现在的加速结构需要对每个 mesh 进行一次构造</li>
<li>需要想办法支持动态改变的网格</li>
</ol>
</li>
<li>增强 high-order 查询的性能
<ol>
<li>现在都是一级的查询（8种）</li>
</ol>
</li>
<li>支持 quad mesh
<ol>
<li>现在全都是三角网格</li>
<li>也许之后还可以支持体积网格</li>
</ol>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] Volumetric Appearance Stylization with Stylizing Kernel Prediction Network</title>
      <link>https://blog.chong-zeng.com/posts/2022-02-13_volumetric_style_transfer/</link>
      <pubDate>Sun, 13 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-02-13_volumetric_style_transfer/</guid>
      <description>1. 这篇文章究竟讲了什么问题？ 通过体积风格转移的方法，来高效地构造颜色外观上符合要求的、异质单反射体积。
网络使用了一个体积的自编码器，并且使用了 stylizing kernel predictor
2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？ 属于改进性质的问题，之前已经有不少人研究过了体积上的风格迁移，但是文章提出的方法能够得到更好的效果。
同时这篇 paper 也属于 Artistic Appearance Design，传统的方法需要较为复杂的人工调整才能得到较好的效果，而本文的方法不需要人工干预，效率更高。
3. 这篇文章致力于证明什么假设？ 证明它的这套风格迁移的框架是 work 的，并且效果很好
4. 有哪些与这篇文章相关的研究？ Neural Style Transfer for Images Neural Style Transfer for 3D Contents Artistic Appearance Design Differentiable Rendering 5. 这篇文章提出的问题解决方案中，核心贡献是什么？ 核心 idea
提出了一个将颜色外观从二维图形转移到三维图形上的框架 细节
设计了一个多尺度的基于 kernel 的神经网络来进行任意的风格迁移并保证时间上的一致性
SKP 首先使用 CNN (VGG) 来提取多个尺度的二维图片上的特征 然后选用 channel-wise 的均值和方差（实际网络中用的是标准差）进行拼接，得到一个特征向量 将这个向量通过一系列全连接层映射到一个 kernel 上 VolAE 经典的 encoder-decoder 结构，中间带有 skip 连接 在 decode 阶段将前面 SKP 得到的 kernel 插入进来，来将二维的风格加入到生成的体积中 引入了一个密度感知的 instance normalization 层，来避免色彩偏移</description>
      <content:encoded><![CDATA[<h1 id="1-这篇文章究竟讲了什么问题">1. 这篇文章究竟讲了什么问题？</h1>
<p>通过体积风格转移的方法，来高效地构造颜色外观上符合要求的、异质单反射体积。</p>
<p>网络使用了一个体积的自编码器，并且使用了 stylizing kernel predictor</p>
<h1 id="2-这个问题的性质是什么如果不完全是一个新问题那为什么它仍然重要">2. 这个问题的性质是什么？如果不完全是一个新问题，那为什么它“仍然重要”？</h1>
<p>属于改进性质的问题，之前已经有不少人研究过了体积上的风格迁移，但是文章提出的方法能够得到更好的效果。</p>
<p>同时这篇 paper 也属于 Artistic Appearance Design，传统的方法需要较为复杂的人工调整才能得到较好的效果，而本文的方法不需要人工干预，效率更高。</p>
<h1 id="3-这篇文章致力于证明什么假设">3. 这篇文章致力于证明什么假设？</h1>
<p>证明它的这套风格迁移的框架是 work 的，并且效果很好</p>
<h1 id="4-有哪些与这篇文章相关的研究">4. 有哪些与这篇文章相关的研究？</h1>
<ul>
<li>Neural Style Transfer for Images</li>
<li>Neural Style Transfer for 3D Contents</li>
<li>Artistic Appearance Design</li>
<li>Differentiable Rendering</li>
</ul>
<h1 id="5-这篇文章提出的问题解决方案中核心贡献是什么">5. 这篇文章提出的问题解决方案中，核心贡献是什么？</h1>
<ul>
<li>
<p>核心 idea</p>
<ul>
<li>提出了一个将颜色外观从二维图形转移到三维图形上的框架</li>
</ul>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/0.png" alt="Untitled.png"  />
</p>
</li>
<li>
<p>细节</p>
<ul>
<li>
<p>设计了一个多尺度的基于 kernel 的神经网络来进行任意的风格迁移并保证时间上的一致性</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/1.png" alt="Untitled%201.png"  />
</p>
<ul>
<li>SKP
<ul>
<li>首先使用 CNN (VGG) 来提取多个尺度的二维图片上的特征</li>
<li>然后选用 channel-wise 的均值和方差（实际网络中用的是标准差）进行拼接，得到一个特征向量</li>
<li>将这个向量通过一系列全连接层映射到一个 kernel 上</li>
</ul>
</li>
<li>VolAE
<ul>
<li>经典的 encoder-decoder 结构，中间带有 skip 连接</li>
<li>在 decode 阶段将前面 SKP 得到的 kernel 插入进来，来将二维的风格加入到生成的体积中</li>
</ul>
</li>
</ul>
</li>
<li>
<p>引入了一个密度感知的 instance normalization 层，来避免色彩偏移</p>
<ul>
<li>
<p>色彩偏移 / 色差</p>
</li>
<li>
<p>为什么会出现色彩偏移？</p>
<ul>
<li>在一些场景里（比如烟雾模拟），voxel 的分布非常不均匀，一些稀疏却非常致密的 voxel 会导致训练困难，进而产生色彩偏移</li>
</ul>
</li>
<li>
<p>解决</p>
<ul>
<li>
<p>使用 DAIN (density-aware instance normalization) 来给这一部分的 voxel 更大的权重</p>
</li>
<li>
<p>加入了一个平滑的密度 mask: $\textbf{m} = 1 - \text{exp}(-\lambda\textbf{V}_\sigma^2)$</p>
</li>
<li>
<p>于是均值和方差变为：</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/2.png" alt="Untitled%202.png"  />
</p>
</li>
</ul>
</li>
<li>
<p>效果</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/3.png" alt="Untitled%203.png"  />
</p>
</li>
</ul>
</li>
<li>
<p>实现了一个分析性的可微体积渲染层，这样可以方便 loss 的计算</p>
<ul>
<li>
<p>分析性 → 简化模型</p>
<ul>
<li>
<p>假设</p>
<ol>
<li>物体的相位函数是各项异性的，且只被环境光照亮</li>
<li>每个 pixel 上只发射一条光线，且只考虑一次散射</li>
</ol>
</li>
<li>
<p>简化模型</p>
<ol>
<li>ray marching 的 sample 是等距离的</li>
</ol>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/4.png" alt="Untitled%204.png"  />
</p>
<ol>
<li>每次 sampling 的辐射度都是从各向异性的相位方程中采样出来的</li>
</ol>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/5.png" alt="Untitled"  />
</p>
</li>
</ul>
</li>
<li>
<p>光源使用环境光，这样可以渲染出比较均匀的体积，避免网络将点光源产生的阴影当作特征进行学习</p>
</li>
<li>
<p>不使用通用的 DTRT 框架，因为太慢了</p>
</li>
</ul>
</li>
<li>
<p>Loss</p>
<ul>
<li>Gran Loss 不好
<ul>
<li>收敛慢</li>
<li>有 artifacts</li>
</ul>
</li>
<li>用 Histogram Loss</li>
<li>另外加上了 total variation loss 和 temporal loss，前者是正则化项，来增强空间平滑性，后者是时域上的平滑性</li>
</ul>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/6.png" alt="Untitled"  />
</p>
</li>
</ul>
</li>
</ul>
<h1 id="6-实验是如何设计的">6. 实验是如何设计的？</h1>
<ol>
<li>使用 pytorch 实现了整个网络，并与以前的方法进行对比</li>
<li>对比不同的 loss function 的效果</li>
<li>对比不同的 kernel、views 的效果</li>
<li>尝试各种场景的 demo</li>
</ol>
<h1 id="7-实验是在什么样的数据集基础上运行的">7. 实验是在什么样的数据集基础上运行的？</h1>
<ol>
<li>volume 数据集
<ul>
<li>使用 mantaflow 生成了大量体积数据集</li>
<li>simulate 100 groups of smokes with a resolution of 64 × 64 × 64</li>
<li>20 * 128 x 128 x 128
<ul>
<li>避免网络对低分辨率的体积过拟合</li>
<li>增加鲁棒性</li>
</ul>
</li>
</ul>
</li>
<li>style image 数据集
<ul>
<li>DTD 数据集</li>
</ul>
</li>
</ol>
<h1 id="8-实验结果能否有力地支持假设">8. 实验结果能否有力地支持假设？</h1>
<ol>
<li>
<p>与传统方法对比是投票投出来的</p>
<ol>
<li>user study</li>
</ol>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/7.png" alt="Untitled"  />
</p>
<p>b. 不过确实，风格迁移不太好有非常量化的评价指标，毕竟不存在 ground truth</p>
</li>
<li>
<p>loss 效果好</p>
<ol>
<li>
<p>histogram loss 最符合输入图片的色彩分布</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/8.png" alt="Untitled"  />
</p>
</li>
<li>
<p>temporal loss</p>
<p>加上之后可以消除 flicker</p>
</li>
</ol>
</li>
<li>
<p>不同的 kernel</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/9.png" alt="Untitled"  />
</p>
<p>作者对比了一大堆，但是毕竟我们也不知道 ground truth，所以其实只是呈现了一些不同的效果</p>
</li>
<li>
<p>训练所用的视角数量</p>
<p>越多越好，符合直觉</p>
<p><img loading="lazy" src="/2022-02-15_volumetric_style_transfer.assets/10.png" alt="Untitled"  />
</p>
</li>
<li>
<p>其他 demo</p>
<ol>
<li>通过调整 volume 的分辨率可以调整风格结构的尺寸</li>
<li>这套方法能够模拟玉石这种半透明材料
<ol>
<li>只要输入的风格图片是真实世界中的半透明材料上采集的即可</li>
</ol>
</li>
<li>可以模拟动态的火焰</li>
</ol>
</li>
</ol>
<h1 id="9-这篇文章的贡献是什么">9. 这篇文章的贡献是什么？</h1>
<ol>
<li>提出了一个将颜色外观从二维图形转移到三维图形上的通用框架</li>
<li>设计了一个多尺度的基于 kernel 的神经网络来进行任意的风格迁移，并保证了时域上的一致性</li>
<li>引入了一个 DAIN 层，来避免色彩偏移</li>
<li>实现了一个简化的可微体积渲染层，方便 loss 的计算，提高训练效率</li>
</ol>
<h1 id="10-下一步可以做什么">10. 下一步可以做什么？</h1>
<ol>
<li>缺少细节
<ol>
<li>比如毛发、纤维这种都还不行</li>
<li>因为直接使用的是均值和方差，可能需要补充更多的统计信息</li>
</ol>
</li>
<li>没法对体积本身进行同时的风格迁移
<ol>
<li>尝试套用 TNST，但是效果并不是很好</li>
<li>需要探索一种联合迁移优化的方案</li>
</ol>
</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] Antithetic Sampling for Monte Carlo Differentiable Rendering</title>
      <link>https://blog.chong-zeng.com/posts/2022-02-12_dual_diff/</link>
      <pubDate>Sat, 12 Feb 2022 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2022-02-12_dual_diff/</guid>
      <description>Disclaimer:
这几篇 paper reading 是我去年暑期在 MSRA 实习期间留下的笔记，近期整理文件翻出遂转至博客。其中的内容不保证正确性，观点仅供参考。 “十问” 的格式来源于沈向洋老师的分享，指路 👉 1. 这篇文章究竟讲了什么问题？ 蒙特卡洛可微渲染中的对偶采样 问题： 可微渲染：渲染是在3D场景中进行积分得到2D图片，可微渲染就是逆向渲染的一个方法，通过微分从2D图片得到3D场景的部分参数 本文主要研究的是 physical-based 可微渲染，不是光栅化那种的 传统的 sampling 方法在面对高光表面的时候，会非常低效，尤其是在对全局的几何求导的时候 引入对偶采样可以大幅提高采样效率 2. 这个问题的性质是什么？它的重要性何在？ 对于传统方法的改进，解决掉了传统的 sampling 方法在面对高光物体时的低效问题 重要性： 计算制造、计算成像、遥感 不过感觉高光这件事在成像上重要一些，遥感这种远场的情况很少出现高光 完善了以往的方法，使得整个 BSDF 的对偶采样框架有更好的普适性 3. 这篇文章致力于证明什么假设？ 利用了对偶采样的蒙特卡洛算法能够很好的估计内部积分，从而使得整个采样框架具有更好的效率和普适性
4. 有哪些与这篇文章相关的研究？这一领域有哪些关键人物？ 本文的作者（Zhao Shuang）就是专门做可微渲染的，在去年的 SIGGRAPH20 上给了一个可微渲染的 course，CVPR21 又给了一个 tutorial talk Wenzel Jakob, 开发了 mitsuba2 的团队，mitsuba2 主要解决了可微渲染中高性能 auto diff 的问题 还有 Tzu-Mao Li 老师 5. 这篇文章提出的问题解决方案中，核心贡献是什么？ 面对高光表面，蒙特卡洛为什么慢？
When 𝐹 contains high-magnitude positive and negative regions, estimating 𝐼 using Monte Carlo methods with independent samples can suffer from very slow convergence.</description>
      <content:encoded><![CDATA[<blockquote>
<p>Disclaimer:</p>
<ol>
<li>这几篇 paper reading 是我去年暑期在 MSRA 实习期间留下的笔记，近期整理文件翻出遂转至博客。其中的内容不保证正确性，观点仅供参考。</li>
<li>“十问” 的格式来源于沈向洋老师的分享，指路 <a href="https://zhuanlan.zhihu.com/p/163227375">👉</a></li>
</ol>
</blockquote>
<h1 id="1-这篇文章究竟讲了什么问题">1. 这篇文章究竟讲了什么问题？</h1>
<ol>
<li>蒙特卡洛可微渲染中的对偶采样</li>
<li>问题：
<ol>
<li>可微渲染：渲染是在3D场景中进行积分得到2D图片，可微渲染就是逆向渲染的一个方法，通过微分从2D图片得到3D场景的部分参数</li>
<li>本文主要研究的是 physical-based 可微渲染，不是光栅化那种的</li>
<li>传统的 sampling 方法在面对高光表面的时候，会非常低效，尤其是在对全局的几何求导的时候</li>
<li>引入对偶采样可以大幅提高采样效率</li>
</ol>
</li>
</ol>
<h1 id="2-这个问题的性质是什么它的重要性何在">2. 这个问题的性质是什么？它的重要性何在？</h1>
<ol>
<li>对于传统方法的改进，解决掉了传统的 sampling 方法在面对高光物体时的低效问题</li>
<li>重要性：
<ol>
<li>计算制造、计算成像、遥感
<ol>
<li>不过感觉高光这件事在成像上重要一些，遥感这种远场的情况很少出现高光</li>
</ol>
</li>
<li>完善了以往的方法，使得整个 BSDF 的对偶采样框架有更好的普适性</li>
</ol>
</li>
</ol>
<h1 id="3-这篇文章致力于证明什么假设">3. 这篇文章致力于证明什么假设？</h1>
<p>利用了对偶采样的蒙特卡洛算法能够很好的估计<strong>内部积分</strong>，从而使得整个采样框架具有更好的效率和普适性</p>
<h1 id="4-有哪些与这篇文章相关的研究这一领域有哪些关键人物">4. 有哪些与这篇文章相关的研究？这一领域有哪些关键人物？</h1>
<ol>
<li>本文的作者（Zhao Shuang）就是专门做可微渲染的，在去年的 SIGGRAPH20 上给了一个可微渲染的 course，CVPR21 又给了一个 tutorial talk</li>
<li>Wenzel Jakob, 开发了 mitsuba2 的团队，mitsuba2 主要解决了可微渲染中高性能 auto diff 的问题</li>
<li>还有 Tzu-Mao Li 老师</li>
</ol>
<h1 id="5-这篇文章提出的问题解决方案中核心贡献是什么">5. 这篇文章提出的问题解决方案中，核心贡献是什么？</h1>
<ol>
<li>
<p>面对高光表面，蒙特卡洛为什么慢？</p>
<ol>
<li>When 𝐹 contains high-magnitude positive and negative regions, estimating 𝐼 using Monte Carlo methods with independent samples can suffer from very slow convergence.</li>
<li>简单说就是当被积分的函数包含尺度很大的正负区域的时候，蒙特卡洛方法很难收敛</li>
<li>而高光区域就是这个特点，所以难以快速收敛</li>
</ol>
</li>
<li>
<p>如何加速蒙特卡洛采样？</p>
<ol>
<li>如果被采样的函数是一个<strong>偶函数</strong>，那么一般采用对偶采样的方法，可以大大降低所需的样本数（因为样本的方差变小了）</li>
</ol>
</li>
<li>
<p>为什么可以用对偶采样？</p>
<ol>
<li>
<p>采样的函数需要是偶函数</p>
</li>
<li>
<p>Our key observation is that geometric derivatives of BSDFs, under certain parameterizations, are approximately odd functions.</p>
<ol>
<li>
<p>为什么呢？</p>
<ol>
<li>
<p>首先作者使用的是一个 microfacet 的 BSDF 函数</p>
<p>$$f_s(\omega_\text{i},\omega_\text{o})=D(\omega_\text{h})f_s^{(0)}(\omega_\text{i},\omega_\text{o})$$</p>
<p>D 是正态分布函数，omega_h 是半向量</p>
<p>将这个BSDF函数求导得到：</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled.png" alt="Untitled.png"  />
</p>
<p>其中的 $f_s^{(0)}$ 和 $d_{f_s}/d\theta$ 很少变化，而 D 在高光区域变化非常大</p>
</li>
</ol>
<p>因此作者提出：</p>
<ol>
<li>
<p>Beckmann、GGX 等常见模型里，D 都是对称的</p>
</li>
<li>
<p>而且在一个局部坐标系里，如果按照 z 轴对齐，D 更是偶函数了</p>
<p>下图是他们对于这个 insight 可视化的结果</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_1.png" alt="Untitled%201.png"  />
</p>
</li>
</ol>
</li>
</ol>
</li>
</ol>
</li>
<li>
<p>核心算法：</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_2.png" alt="Untitled%202.png"  />
</p>
<p>注意：对偶采样只有在高光部分才会使用，这个是文章的 algorithm 2 主要表明的 idea</p>
</li>
<li>
<p>光路的对偶采样</p>
<p>作者发现对偶采样技术可以适配到 path-level</p>
<ol>
<li>
<p>单向 unidirectional</p>
<p>就是在每个高光的地方做一次对偶，比如下图中就是p3和p4</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_3.png" alt="Untitled%203.png"  />
</p>
</li>
<li>
<p>双向 bidirectional</p>
<p><img loading="lazy" src="/2022-02-15_Dual_Diff.assets/Untitled_4.png" alt="Untitled%204.png"  />
</p>
<p>通过对偶采样一个对偶的 source path 和一个对偶的 detector path（图里没画），然后普通的path 和对偶的 path 都要连起来</p>
</li>
</ol>
</li>
</ol>
<h1 id="6-实验是如何设计的">6. 实验是如何设计的？</h1>
<ol>
<li>
<p>Differential rendering comparison</p>
<p>可微部分，比较 Equal quality &amp; Equal time 下的微分结果</p>
<p>作者选用了 6 个带有高光的场景（4个各向同性的 BSDF，2个各向异性的 BRDF），并整合了 edge sampling、unidirectional、bidirectional 等技术，在上面对比使用和不使用对偶采样的效果</p>
</li>
<li>
<p>Inverse-rendering comparison</p>
<p>使用对偶采样得到的微分结果进行逆向渲染，在 bunny、杯子、爱因斯坦画像上进行逆向渲染。</p>
</li>
</ol>
<h1 id="7-实验是在什么样的数据集基础上运行的读文章的人是否能接触到文中所用的数据集">7. 实验是在什么样的数据集基础上运行的？读文章的人是否能接触到文中所用的数据集？</h1>
<p>全都是 CG 里的经典物体/场景了，比如 Cornell Box、Stanford bunny</p>
<h1 id="8-实验结果能否有力地支持假设">8. 实验结果能否有力地支持假设？</h1>
<p>可以。</p>
<ol>
<li>微分结果上：无论是相同时间比质量，还是相同质量比时间，都是吊打以往的方法</li>
<li>逆向渲染上：传统方法会因高光处的噪声太多导致无法平滑的收敛，而加入了对偶渲染的技术之后，收敛的速度和结果都好很多</li>
</ol>
<h1 id="9-这篇文章的贡献是什么">9. 这篇文章的贡献是什么？</h1>
<p>作者发现对于高光表面，其BSDF函数往往在局部是偶函数，因此使用对偶采样可以加速蒙特卡洛采样的收敛速度，从而加快求导的速度。</p>
<h1 id="10-下一步可以做什么">10. 下一步可以做什么？</h1>
<ol>
<li>对偶采样与其他技术都是正交的，也就是说可以整合更多的前向渲染中的技术进来</li>
<li>对偶采样只解决了内部积分的问题，高光材质的<strong>边界积分</strong>估计还没被解决</li>
</ol>
]]></content:encoded>
    </item>
    <item>
      <title>[Paper Reading] Efficient Reflectance Capture Using an Autoencoder</title>
      <link>https://blog.chong-zeng.com/posts/2021-08-05_efficient-reflectance-capture-using-an-autoencoder/</link>
      <pubDate>Thu, 05 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2021-08-05_efficient-reflectance-capture-using-an-autoencoder/</guid>
      <description>1 导言 从现实世界中采集高精度的材质信息是一件非常重要而又非常具有挑战性的问题。这个问题可以被建模为空间变化的双向反射分布函数（SVBRDF）的采集，即一个六维的随位置、光照、视角变化而变化的函数。直接采集一个未知的 SVBRDF 函数需要上千张照片，因为你需要足够多的样本去涵盖所有可能的位置、光照、视角，这也直接导致了直接采集在时间和储存上的高成本。
为此，人们开展了很多关于提升采集效率的工作。一类主流的方法就是通过设计精巧的光照模式来实现采样的”并行化“，即在一次拍摄中尽可能采集更多的组合。但是即便是此前最好的解决方案（Guojun Chen, 2014. Reflectance Scanning: Estimating Shading Frame and BRDF with Generalized Linear Light Sources），也需要采集上百张照片。这使得这项技术在落地时仍然遇到巨大的困难。
为此，论文作者提出两个基于光照模式的反射采集方法的根本性问题：
在光照模式的数量有限的情况下，到底什么光照模式是最优的？ 如何从这些模式下采集的照片中，还原出原本的物体？ 以往的工作对于前两个问题的回答都是手工操作，也就是通过手工推导来设计各种复杂的光照模式，然后再解算出重建的方法。但是这样的方法有两个问题：1. 光照模式的数量往往取决于推导的方法，而无法任意根据所需的精度进行选择；2. 这些光照模式并没有在足够多的实际数据中进行其有效性的验证。
因此，论文作者选择使用数据驱动的方法，自动从大量真实物体的材质数据中学到最优的光照模式。
2 相关工作 2.1 直接采样 直接采样就是通过遍历 SVBRDF 的不同参数组合，来重建出整个 SVBRDF 函数。这一系列的工作精度非常的高，但工作量也非常的大，耗时很久，效率很低。
2.2 优化采样 这一方向主要是是增加假设来对于 BRDF 采样本身进行优化，比如 Matusik 等人通过假设一个任意的 BRDF 函数都落在一个预先捕捉好的各向同性的子空间中，成功将采样数量降低到了 800 张。而 Nielsen 等人通过一个能够优化光照和视角的改进算法，将采样数量降低到了 20 张。Xu 等人在 2016 年甚至通过在近场相机忽略掉视角的变化，将采样数降低到了 2 张，并通过假设表面没有法向的变化，将方法拓展到了各向同性的 SVBRDF 上。
2.3 复杂光照模式 但是增加假设的方法对于真实世界中的绝大多数情况都是不具有拓展性的，因此另一个方向是优化采集本身的效率。[Gardener et al. 2003; Ghosh et al. 2009; Aittala et al.</description>
      <content:encoded><![CDATA[<h1 id="1-导言">1 导言</h1>
<p>从现实世界中采集高精度的材质信息是一件非常重要而又非常具有挑战性的问题。这个问题可以被建模为空间变化的双向反射分布函数（SVBRDF）的采集，即一个六维的随位置、光照、视角变化而变化的函数。直接采集一个未知的 SVBRDF 函数需要上千张照片，因为你需要足够多的样本去涵盖所有可能的位置、光照、视角，这也直接导致了直接采集在时间和储存上的高成本。</p>
<p>为此，人们开展了很多关于提升采集效率的工作。一类主流的方法就是通过设计精巧的光照模式来实现采样的”并行化“，即在一次拍摄中尽可能采集更多的组合。但是即便是此前最好的解决方案（Guojun Chen, 2014. Reflectance Scanning: Estimating Shading Frame and BRDF with Generalized Linear Light Sources），也需要采集上百张照片。这使得这项技术在落地时仍然遇到巨大的困难。</p>
<p>为此，论文作者提出两个基于光照模式的反射采集方法的根本性问题：</p>
<ol>
<li>在光照模式的数量有限的情况下，到底什么光照模式是最优的？</li>
<li>如何从这些模式下采集的照片中，还原出原本的物体？</li>
</ol>
<p>以往的工作对于前两个问题的回答都是手工操作，也就是通过手工推导来设计各种复杂的光照模式，然后再解算出重建的方法。但是这样的方法有两个问题：1. 光照模式的数量往往取决于推导的方法，而无法任意根据所需的精度进行选择；2. 这些光照模式并没有在足够多的实际数据中进行其有效性的验证。</p>
<p>因此，论文作者选择使用<strong>数据驱动</strong>的方法，<strong>自动</strong>从大量真实物体的材质数据中学到最优的光照模式。</p>
<h1 id="2-相关工作">2 相关工作</h1>
<h2 id="21-直接采样">2.1 直接采样</h2>
<p>直接采样就是通过遍历 SVBRDF 的不同参数组合，来重建出整个 SVBRDF 函数。这一系列的工作精度非常的高，但工作量也非常的大，耗时很久，效率很低。</p>
<h2 id="22-优化采样">2.2 优化采样</h2>
<p>这一方向主要是是增加假设来对于 BRDF 采样本身进行优化，比如 Matusik 等人通过假设一个任意的 BRDF 函数都落在一个预先捕捉好的各向同性的子空间中，成功将采样数量降低到了 800 张。而 Nielsen 等人通过一个能够优化光照和视角的改进算法，将采样数量降低到了 20 张。Xu 等人在 2016 年甚至通过在近场相机忽略掉视角的变化，将采样数降低到了 2 张，并通过假设表面没有法向的变化，将方法拓展到了各向同性的 SVBRDF 上。</p>
<h2 id="23-复杂光照模式">2.3 复杂光照模式</h2>
<p>但是增加假设的方法对于真实世界中的绝大多数情况都是不具有拓展性的，因此另一个方向是优化采集本身的效率。[Gardener et al. 2003; Ghosh et al. 2009; Aittala et al. 2013] 等三篇论文都尝试通过使用复杂的照明模式来实现光路复用，不过这几篇文章的作者都是手工设计的照明模式。</p>
<h2 id="24-深度学习辅助的反射建模">2.4 深度学习辅助的反射建模</h2>
<p>[Aittala et al. 2016; Li et al. 2017] 两篇工作采用了深度学习来辅助反射建模。Aittala 等人使用单视角的闪光单张照片来建模各向同性的 SVBRDF 和表面法向。Li 等人的工作则能够使用未知的自然光照下的单张照片实现反射建模，通过一个基于 CNN 的网络，经过自增强训练，重建出材质的 SVBRDF 函数。</p>
<h1 id="3-核心框架">3 核心框架</h1>
<h2 id="31-问题形式化">3.1 问题形式化</h2>
<h3 id="311-假设条件">3.1.1 假设条件</h3>
<p>不失一般性，我们假设有一个近场光源，光源中的每一个点都可以被独立控制。装置被假设校准好且相机镜头不带偏振。需要采集的物体被假设为一个理想平面，而材质本身被表示为一个各向异性的 SVBRDF 函数，平面物体上的每个点需要进行独立的采集重建。</p>
<h3 id="312-记号">3.1.2 记号</h3>
<p>此外我们需要定义一些记号：</p>
<table>
<thead>
<tr>
<th>记号</th>
<th>含义</th>
</tr>
</thead>
<tbody>
<tr>
<td>$x_p$</td>
<td>物体样本上 $p$ 点的位置</td>
</tr>
<tr>
<td>$n_p$</td>
<td>物体样本上 $p$ 点的法向</td>
</tr>
<tr>
<td>$x_l$</td>
<td>灯珠 $l$ 的位置</td>
</tr>
<tr>
<td>$n_l$</td>
<td>灯珠 $l$ 的法向</td>
</tr>
<tr>
<td>$\omega_i$</td>
<td>世界坐标系下光照方向</td>
</tr>
<tr>
<td>$\omega_o$</td>
<td>世界坐标系下观察方向</td>
</tr>
<tr>
<td>$\omega&rsquo;_i$</td>
<td>物体坐标系下光照方向</td>
</tr>
<tr>
<td>$\omega&rsquo;_o$</td>
<td>物体坐标系下观察方向</td>
</tr>
<tr>
<td>$I(l)$</td>
<td>灯珠 $l$ 的可编程亮度，取值范围 $[0, 1]$</td>
</tr>
<tr>
<td>$\Psi$</td>
<td>描述灯珠在最大亮度时，亮度随角度的分布</td>
</tr>
<tr>
<td>$f_r$</td>
<td>二维 BRDF 切片</td>
</tr>
<tr>
<td>$\rho_d$</td>
<td>漫反射反照率</td>
</tr>
<tr>
<td>$\rho_s$</td>
<td>镜面反射反照率</td>
</tr>
<tr>
<td>$\alpha_x$</td>
<td>粗糙程度</td>
</tr>
<tr>
<td>$\omega_h$</td>
<td>半向量方向</td>
</tr>
<tr>
<td>$F$</td>
<td>菲涅耳系数</td>
</tr>
<tr>
<td>$G_\text{GGX}$</td>
<td>阴影遮罩系数</td>
</tr>
<tr>
<td>$B$</td>
<td>观测辐射值</td>
</tr>
<tr>
<td>$m$</td>
<td>Lumitexel 亮素</td>
</tr>
</tbody>
</table>
<h3 id="313-测量方程">3.1.3 测量方程</h3>
<p>这样我们就可以定义出特定光照下一点的辐射值：</p>
<p>$$
B(I, \mathbf{p})= \int \frac{1}{\left|\mathbf{x}{\mathbf{l}}-\mathbf{x}{\mathbf{p}}\right|^{2}} I(l) \Psi\left(\mathbf{x}{\mathbf{l}},-\omega_{\mathbf{i}}\right) f_{r}\left(\omega_{\mathbf{i}}^{\prime} ; \omega_{\mathbf{o}}^{\prime}, \mathbf{p}\right) \left(\omega_{\mathbf{i}} \cdot \mathbf{n}_{\mathbf{p}}\right)\left(-\omega_i\cdot n_l\right) d x_l
$$</p>
<p>其中 $\omega_i$ 可以被表示为 $\omega_i=\frac{x_l-x_p}{\left|x_l-x_p\right|}$</p>
<h3 id="314-brdf-表示">3.1.4 BRDF 表示</h3>
<p>BRDF 函数的表示形式选用了各向异性的 GGX BRDF 函数：</p>
<p>$$
f_{r}\left(\omega_{\mathrm{i}} ; \omega_{\mathbf{0}}, \mathbf{p}\right)
= \frac{\rho_{d}}{\pi}+\rho_{s} \frac{D_{\mathrm{GGX}}\left(\omega_{\mathbf{h}} ; \alpha_{x}, \alpha_{y}\right) F\left(\omega_{\mathbf{i}}, \omega_{\mathbf{h}}\right) G_{\mathrm{GGX}}\left(\omega_{\mathbf{i}}, \omega_{\mathbf{o}} ; \alpha_{\mathbf{x}}, \alpha_{\mathbf{y}}\right)}{4\left(\omega_{\mathbf{i}} \cdot \mathbf{n}\right)\left(\omega_{\mathbf{0}} \cdot \mathbf{n}\right)}
$$</p>
<p>作者选用 GGX 的考虑主要有以下三点：</p>
<ol>
<li>GGX 是一个参数化模型，且非常“紧凑”，能够表示非常广泛的材料</li>
<li>GGX 已经是 PBR （基于物理渲染）的行业标准</li>
<li>GGX 能够实现高效的实时渲染</li>
</ol>
<h3 id="315-lumitexel">3.1.5 Lumitexel</h3>
<p>亮素（亮光像素），其实就是将物体的每一个点视为一个 pixel，然后在上面储存该点在不同方向光照下的高光数据。</p>
<p>作者在 slide 里的插图对于 Lumitexel 给出了比较形象的展示：</p>
<ul>
<li>
<p>Lumitexel 本身是一个物体的客观属性，标记了物体上的一个点在受到来自某个单一方向的标准亮度光照照射时，所反射出来的光线亮度</p>
<!-- raw HTML omitted -->
</li>
<li>
<p>将 Lumitexel 与实际的光照模式直接相乘，就得到了采集到的测量结果</p>
<!-- raw HTML omitted -->
</li>
</ul>
<p>Lumitexel 形式化表示如下：
$$
m(j ; \mathbf{p})=B({I(l=j)=1, I(l \neq j)=0}, \mathbf{p})
$$
而观测到的辐射值在物理上其实就是 Lumitexel 与照明模式的点积：
$$
B(I, \mathrm{p})=\sum_{l} I(l) m(l ; \mathrm{p})
$$</p>
<h3 id="316-问题定义">3.1.6 问题定义</h3>
<p>物体材质的采集本质就是在给定物体某一点 $\text{p}$ 的参数 ${\rho_d, \rho_s, \alpha_x, \alpha_y, \text{n}, \text{t}}$ 、一批光照模式 ${I(l\text{p})}_I$ 以及对应光照模式下实际采集到的辐射值 ${B(I, \text{p})}_I$ ，求解一个未知的 BRDF 函数 $f_r$。</p>
<h2 id="32-求解思路与工作框架">3.2 求解思路与工作框架</h2>
<p>问题的本质其实已经在形式化部分给出，简单来说就是下面这张图所需要解的问题：</p>
<!-- raw HTML omitted -->
<p>其中最左边的 Lumitexel 是未知但固有存在的物理属性，中间的光照模式是需要设计的，测量值是客观测量出来的，而最右边的 BRDF 是要求解的。</p>
<p>而这本质是一个编码解码的过程：光照是对物体材质属性的物理编码，而求解就是一个解码过程，可以概括为下图：</p>
<!-- raw HTML omitted -->
<p>以往的方法无论是光照模式还是解码方式，都是手工设计的——这样会带来两个问题：模式不一定最优且模式数量难以降低，进而导致了采样效率低下。于是文章的作者创新性地提出可以使用网络来自动优化出最合适的编码解码方式。</p>
<p>一般来说，最直接的想法是解码器直接从观测值拟合到 BRDF 函数。这一设计非常端到端，但是作者意识到这个映射并不是一个单射关系，而是一个一对多的关系——一个实际的物体其实可以被多组 BRDF 参数描述，典型的就是假如某一点的镜面反射率为 0，那么在法向和漫反射率确定的情况下，其他参数可以任意变化；再比如 BRDF 中的切向 tangent 值可以为正也可以为负，而不影响其含义。这种性质对于回归模型非常不友好。</p>
<p>因此，作者决定使用自编码器 AutoEncoder，来规避这种一对多的关系；而如果对 BRDF 本身进行自编码，会需要引入相机的视角等信息，从而增加网络的复杂度，而且模型会与 BRDF 形式的耦合，每更换一个 BRDF 函数就需要重新训练整个网络；另一方面，从 Lumitexel 到 BRDF 的拟合方法已经非常成熟，并不需要用网络就可以完成；由此作者直接选用 Lumitexel 作为自编码的对象，提出了下面的工作流程：</p>
<p><img loading="lazy" src="/2021-08-05_Efficient-Reflectance-Capture-Using-an-Autoencoder.assets/image-20210627202100536.png" alt="image-20210627202100536"  />
</p>
<h2 id="33-模型结构与损失函数">3.3 模型结构与损失函数</h2>
<h3 id="331-l-dae">3.3.1 L-DAE</h3>
<!-- raw HTML omitted -->
<p>作者把这个自编码 Lumitexel 的网络称为 L-DAE (Lumitexel Deep AutoEncoder)。</p>
<p>对于 L-DAE 的编码器部分，作者将所有的照明模式视为一个 $c \times 1 \times \sharp$ 的卷积核，其中 $c$ 是 Lumitexel 的维度，而 $\sharp$ 代表光照模式的个数。这是硬件设计所产生的约束——每个卷积核的权重都对应了一颗灯珠在一种照明模式下的亮度，所以编码器必须是线性的。不过由于输入的 Lumitexel 维度其实与卷积核的第一个维度一样，整个卷积层其实与一个全连接层是等价的。</p>
<p>而对于解码器部分，由于它是直接运行在计算设备上而非物理采集设备上，所以没有任何的限制。于是作者决定不加入任何假设和先验知识，直接使用 11 层全连接层，构造出一个非线性的解码器。使得解码器能够实现非常复杂的解码任务。</p>
<p>完整的网络结果如下图所示：</p>
<!-- raw HTML omitted -->
<h3 id="332-损失函数">3.3.2 损失函数</h3>
<p>L-DAE 的损失函数包含了两个部分：自编码器的解码误差与 Lumitexel 物理意义上的硬性约束。
$$
L=L_{\text {auto }}(m)+\lambda \sum_{w \in \text { enc. }} L_{\text {barrier }}(w)
$$
自编码器的误差就是输入的 Lumitexel 与重建出来的 Lumitexel 的差异：
$$
L_{\text {auto }}(m)=\sum_{j}\left[\log (1+m(j))-\log \left(1+m_{\mathrm{gt}}(j)\right)\right]^{2}
$$
注意到作者引入了 $log$ 来缓解镜面反射所带来的高光对于损失造成过大的影响。</p>
<p>而由于 Lumitexel 每个值的取值范围都应当在 $[0, 1]$ 之间，作者引入了一个 barrier 损失来刻画对于超出物理取值范围的点的惩罚：
$$
L_{\text {barrier }}(w)=\tanh \left(\frac{w-(1-\epsilon)}{\epsilon}\right)+\tanh \left(\frac{-w+\epsilon}{\epsilon}\right)+2
$$
在实验中，作者发现 $\lambda=0.03, \epsilon=0.005$ 是一组不错的参数。</p>
<h1 id="4-采集实验">4 采集实验</h1>
<p>为了验证方法的可行性，作者进行了真实的采集实验。</p>
<h2 id="41-设备搭建">4.1 设备搭建</h2>
<p>作者首先搭建了一个近场 lightstage （我也不知道中文这个叫啥好，英文非常形象）。lightstage 的底部放置了要采集的平面物体，其他五面环绕了 LED 灯板，如下如所示：</p>
<!-- raw HTML omitted -->
<p>将灯板展开后，我们可以得到下面的图示：</p>
<!-- raw HTML omitted -->
<p>与所有的采集装置一样，整个 lightstage 对相机的内参外参畸变参数、以及灯板的位置进行了校准，得到了精确的空间位置关系。</p>
<p>另外为了实现相机快门与 LED 光照模式的同步，作者使用了 Altera（Intel） 的 Cyclone FPGA 进行高精度控制。亮度上使用了 8-bit 进行刻画，可以描述 256 种不同的亮度。由于装置是近场装置，不同角度与距离对于灯珠光线的衰减影响可以忽略不计。LED 的灯珠颜色使用了 X-Rite 校色仪进行修正。漫反射与镜面反射的尺度模糊问题使用了一个平面均匀漫反射贴片来解决。</p>
<h2 id="42-模型训练">4.2 模型训练</h2>
<p>作者使用纹理生成的方法，利用大量真实世界的物体数据，结合装置的校准结果，随机采样生成了 1,000,000,000 (1 million) 个 Lumitexel，然后交给网络进行训练。</p>
<p>网络使用了 RMSProp 作为优化器；对于编码器的权重使用了正太分布进行初始化，并翻转了为负的权重；对于解码器，使用了 xavier 算法进行初始化。</p>
<h2 id="43-其他实现细节">4.3 其他实现细节</h2>
<p>所有输入的 Lumitexel 都被减去了均值——感觉在机器学习里这是个常规操作了，不管是 PCA 还是其他降维的方法。在物理采集的时候，这个均值会乘上光照模式后在采样结果上减去，然后经过解码之后再加上。</p>
<p>BRDF 的拟合上，作者使用了一个各向异性的 GGX 模型，并使用 Levenberg-Marquardt 算法来对参数拟合出来的结果与实际结果的方差进行优化。</p>
<h1 id="5-实验结果">5 实验结果</h1>
<h2 id="51-时间消耗">5.1 时间消耗</h2>
<p>网络的训练大约持续了 5 小时；训练好的模型编码速度（硬件采集拍摄）大概在 12~25 秒（取决于材质所需的曝光时间以及选用的光照模式数量）；每 1M 大小的 Lumitexel 大约需要 4 分钟解码和 1.6 小时来进行最后的 BRDF 拟合。</p>
<h2 id="52-光照模式">5.2 光照模式</h2>
<p>将模型学习到的线性编码器的每一个模式可视化出来，可以得到下面的一张图：图片从上到下每一列分别是各向异性样本的学习结果、各向同性样本的学习结果、PCA 降维直接得到的结果。可以明显看到这些光照模式都非常复杂，不是人能轻易设计出来的；而模型学习出来的模式是最复杂的。</p>
<!-- raw HTML omitted -->
<h2 id="53-拍摄结果">5.3 拍摄结果</h2>
<p>使用训练出来的光照模式进行采集拍摄，所有的拍摄照片使用两张 SDR 照片合成出一张 HDR 照片，以获得更广泛的亮度范围。</p>
<p>将不同的光照模式拍摄得到的照片与光照模式一起并排放置，可以得到下面的结果：</p>
<!-- raw HTML omitted -->
<p>可以看到，每一张照片看起来都非常不同，这也充分说明这一方法采集的效率之高，在很少的几张照片里涵盖了尽可能多的信息。</p>
<h2 id="54-重建结果">5.4 重建结果</h2>
<p>经过非线性解码和 BRDF 拟合，可以得到下面的重建结果：</p>
<!-- raw HTML omitted -->
<p>其中最后一行是重建结果与 ground truth 的差异，可以看到差异非常的小，说明这一方法的采集精度也非常的高。</p>
<h2 id="55-对比实验">5.5 对比实验</h2>
<h3 id="551-降维策略对比">5.5.1 降维策略对比</h3>
<p>对比 DAE 编码器+非线性解码器、PCA 编码器 + 非线性解码器、DAE 编码器 + 线性解码器、PCA 编码器 + 非线性解码器，可以看到 DAE 编码器+非线性解码器的重建结果是最好的。</p>
<!-- raw HTML omitted -->
<h3 id="552-光照模式数量的影响对比">5.5.2 光照模式数量的影响对比</h3>
<p>调整光照模式的数量，可以看到数量越多，模型训练的 loss 越小，重建效果也越好。</p>
<!-- raw HTML omitted -->
<p>重建结果也映证了这一点：</p>
<!-- raw HTML omitted -->
<h3 id="553-鲁棒性">5.5.3 鲁棒性</h3>
<p>作者增加了不同的高斯噪声，来模拟拍摄时引入的噪声。拟合结果显示这一方法对于不同程度的噪声都表现出很强的抵抗性。</p>
<!-- raw HTML omitted -->
<h3 id="554-训练数据集分布">5.5.4 训练数据集分布</h3>
<p>作者还对比了对于某一个给定的样本，使用不同的训练数据会对采样效率产生什么样的影响。从左到右分别是基准方法（直接采样）、使用了各向异性的样本、使用了各向同性的样本、以及将待采集的样本放入训练集中所需要的光照模式数量。</p>
<!-- raw HTML omitted -->
<p>可以看出，为了达到相同的重建效果，预设的信息越多、需要采集的信息就越少、从而使得光照模式数量变少。</p>
<h1 id="6-局限和展望">6 局限和展望</h1>
<p>这一方法有以下局限：</p>
<ol>
<li>
<p>由于使用了数据驱动的编码器设计方法，所以在面对与数据集显著不同的数据时，模型的重建结果会非常的差，比如下图中的双向高光，就难以被重建：</p>
<!-- raw HTML omitted -->
</li>
<li>
<p>这一方法现在还是只能采集平面物体</p>
</li>
<li>
<p>这一方法目前只利用到了一个视角</p>
</li>
</ol>
<p>不过作者在后一年的 SIGGRAPH Asia 19 上的论文解决了后两个问题，实现了基于多视角的立体物体的采集重建。</p>
<p>未来作者表示还会尝试适配这套方法到远场 lightstage、相机视角设计、以及基于图片的重光照问题。</p>
]]></content:encoded>
    </item>
    <item>
      <title>OptiX 入门笔记</title>
      <link>https://blog.chong-zeng.com/posts/2021-08-01_optix/</link>
      <pubDate>Sun, 01 Aug 2021 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2021-08-01_optix/</guid>
      <description>这其实是我大三上图形学大作业的报告，最近整理本科期间的项目，于是把报告里面比较关于 OptiX 的部分拿出来水篇博客做个笔记。
个人认为 API 没有什么讲的价值，所以博客里更多是讲讲关于 OptiX 的编程模型/思想。
另外有关光追基本知识的部分此处也不过多赘述。
1 基本架构 OptiX 的主要结构如上图所示，由光追渲染管线、加速结构、着色器表及相关资源构成。
值得注意的是，OptiX 其实只负责了渲染的部分，也就是说每次 OptiX 程序运行完成后返回的都是一帧渲染好的图像，而建模、交互，甚至包括画面的显示，都不是 OptiX 所负责的。你可以搭配 OpenGL 之类的来完成这些显示窗口的维护和交互工作。
1.1 光追渲染管线 光追渲染管线是整个光追的核心，它负责了光线的发射、相交的检测、每条光线的着色，以及这些全部计算的调度 1.2 加速结构 加速结构 (Acceleration Structure) 加速的其实是相交检测，OptiX 中使用加速结构来标记物体的每个面，然后计算的就是每条光线与加速结构的相交情况 加速结构本身是一个树形的结构，使用加速结构可以加速光线相交检测的遍历 在注册完全部的加速结构后，OptiX 会编译一个查询表，通过这个加速表可以实现非常高效的相交检测 但是需要注意的是，当建模发生变化的时候，加速结构就会发生变化，进而导致查询表的重新编译，所以在 OptiX 中，modeling 的变化会使得计算压力增大 1.3 着色器表 着色器表 (Shader Table) 中储存了各种与最后的着色有关的资源的索引，可以用于索引一次光线追踪中可能用到的所有资源，比如材质、纹理、法向等，通过着色器表，我们可以快速的获取到这些资源，然后完成相关的计算 每次渲染时，由光追渲染管线调度光线的发射，当光线发生相交后，加速结构给出发生相交处的物体的属性索引，然后我们在着色器表中按照索引查找相关的属性和资源，再交给着色器进行最后的着色，就得到了这个像素上这条光线渲染出来的结果。
2 光追可编程渲染管线 与光栅化一样，光追的渲染管线也是可编程的。光追的渲染管线在前面已经解释，其中可以编程的主要是光线发射、相交检测、着色三个部分。
2.1 光线发射 OptiX 可以实现比较复杂的光线发射，指向针对光源进行重要性采样，不过在我们这儿因为场景足够亮，所以没有做相关的定制。
2.2 相交检测 相交检测背后的算法是二叉树 BVH (Bounding Volume Hierachy)，是空间切分技术之一。使用树形组织的加速结构，可以加速相交检测的计算。但是即便如此，依然是一个开销非常大的计算，在没有 RT Core 的传统 GPU 上，只能通过软件模拟的方法实现相关的计算。
而在 RTX GPU 上，这一算法有相关的硬件实现，因此可以得到非常高的运行效率。
在 OptiX 中直接提供的加速结构只有三角网格结构，不过三角网格的建模能力已经非常强了，所以暂时也没有新增其他结构的需求。</description>
      <content:encoded><![CDATA[<blockquote>
<p>这其实是我大三上图形学大作业的报告，最近整理本科期间的项目，于是把报告里面比较关于 OptiX 的部分拿出来<del>水篇博客</del>做个笔记。</p>
<p>个人认为 API 没有什么讲的价值，所以博客里更多是讲讲关于 OptiX 的编程模型/思想。</p>
<p>另外有关光追基本知识的部分此处也不过多赘述。</p>
</blockquote>
<h1 id="1-基本架构">1 基本架构</h1>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115205001513.png" alt="image-20210115205001513"  />
</p>
<p>OptiX 的主要结构如上图所示，由光追渲染管线、加速结构、着色器表及相关资源构成。</p>
<p>值得注意的是，OptiX 其实只负责了渲染的部分，也就是说每次 OptiX 程序运行完成后返回的都是一帧渲染好的图像，而建模、交互，甚至包括画面的显示，都不是 OptiX 所负责的。你可以搭配 OpenGL 之类的来完成这些显示窗口的维护和交互工作。</p>
<h2 id="11-光追渲染管线">1.1 光追渲染管线</h2>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115200919276.png" alt="image-20210115200919276"  />
</p>
<ul>
<li>光追渲染管线是整个光追的核心，它负责了光线的发射、相交的检测、每条光线的着色，以及这些全部计算的调度</li>
</ul>
<h2 id="12-加速结构">1.2 加速结构</h2>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213337256.png" alt="image-20210115213337256"  />
</p>
<ul>
<li>加速结构 (Acceleration Structure) 加速的其实是相交检测，OptiX 中使用加速结构来标记物体的每个面，然后计算的就是每条光线与加速结构的相交情况</li>
<li>加速结构本身是一个树形的结构，使用加速结构可以加速光线相交检测的遍历</li>
<li>在注册完全部的加速结构后，OptiX 会编译一个查询表，通过这个加速表可以实现非常高效的相交检测</li>
<li>但是需要注意的是，当建模发生变化的时候，加速结构就会发生变化，进而导致查询表的重新编译，所以在 OptiX 中，modeling 的变化会使得计算压力增大</li>
</ul>
<h2 id="13-着色器表">1.3 着色器表</h2>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213438107.png" alt="image-20210115213438107"  />
</p>
<ul>
<li>着色器表 (Shader Table) 中储存了各种与最后的着色有关的资源的索引，可以用于索引一次光线追踪中可能用到的所有资源，比如材质、纹理、法向等，通过着色器表，我们可以快速的获取到这些资源，然后完成相关的计算</li>
</ul>
<p>每次渲染时，由光追渲染管线调度光线的发射，当光线发生相交后，加速结构给出发生相交处的物体的属性索引，然后我们在着色器表中按照索引查找相关的属性和资源，再交给着色器进行最后的着色，就得到了这个像素上这条光线渲染出来的结果。</p>
<h1 id="2-光追可编程渲染管线">2 光追可编程渲染管线</h1>
<p>与光栅化一样，光追的渲染管线也是可编程的。光追的渲染管线在前面已经解释，其中可以编程的主要是<strong>光线发射</strong>、<strong>相交检测</strong>、<strong>着色</strong>三个部分。</p>
<h2 id="21-光线发射">2.1 光线发射</h2>
<p>OptiX 可以实现比较复杂的光线发射，指向针对光源进行重要性采样，不过在我们这儿因为场景足够亮，所以没有做相关的定制。</p>
<h2 id="22-相交检测">2.2 相交检测</h2>
<p><a href="https://github.com/iamNCJ/CG-Project/blob/main/report/report.assets/image-20210115213550410.png"><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213550410.png" alt="image-20210115213550410"  />
</a></p>
<p>相交检测背后的算法是<strong>二叉树 BVH</strong> (Bounding Volume Hierachy)，是空间切分技术之一。使用树形组织的加速结构，可以加速相交检测的计算。但是即便如此，依然是一个开销非常大的计算，在没有 RT Core 的传统 GPU 上，只能通过软件模拟的方法实现相关的计算。</p>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213859517.png" alt="image-20210115213859517"  />
</p>
<p>而在 RTX GPU 上，这一算法有相关的硬件实现，因此可以得到非常高的运行效率。</p>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115213943505.png" alt="image-20210115213943505"  />
</p>
<p>在 OptiX 中直接提供的加速结构只有三角网格结构，不过三角网格的建模能力已经非常强了，所以暂时也没有新增其他结构的需求。</p>
<h2 id="23-着色">2.3 着色</h2>
<p><a href="https://github.com/iamNCJ/CG-Project/blob/main/report/report.assets/image-20210115205029106.png"><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115205029106.png" alt="image-20210115205029106"  />
</a></p>
<p>在光线发生与物体的相交后，OptiX 就会调用相关的着色器开始进行颜色的计算。这一部分也是我们对于渲染管线定制最大的部分。</p>
<p>所有的着色器所干的事情，都是根据相交点的相交类型及相关信息，计算该束光应该拥有什么颜色。</p>
<h3 id="231-最近相交-closest-hit">2.3.1 最近相交 (Closest Hit)</h3>
<p>最近相交，顾名思义就是所有相交中距离相机最近的一个。这样就自然实现了深度检测，而不需要 Z-buffer 之类的辅助。</p>
<h3 id="232-任意相交-any-hit">2.3.2 任意相交 (Any Hit)</h3>
<p>与最近相交不同，任意相交就是所有可以与光线发生相交的地方被调用的着色函数。下面的图非常形象的展示了两者的关系，其中上半部分是 Any Hit，下半部分是 Closest Hit。</p>
<p><img loading="lazy" src="/2021-08-01_OptiX.assets/image-20210115215816573.png" alt="image-20210115215816573"  />
</p>
<h3 id="233-无相交-miss">2.3.3 无相交 (Miss)</h3>
<p>假如光线没有与任何加速结构发生相交，那么最后它将打到无穷远处，进而弱到无法获得任何亮度和颜色。我们可以利用这种情况实现天空盒。</p>
]]></content:encoded>
    </item>
    <item>
      <title>NeRF-Related Review 2020</title>
      <link>https://blog.chong-zeng.com/posts/2021-02-24_nerf/</link>
      <pubDate>Sun, 27 Dec 2020 00:00:00 +0000</pubDate>
      <guid>https://blog.chong-zeng.com/posts/2021-02-24_nerf/</guid>
      <description>2020 年，在 CV/CG 界，一篇叫做 NeRF 的论文爆火，“只需要输入少量静态图片，就能做到多视角的逼真3D效果。”但是实际上，在这篇论文之前，学术界已经有不少这方面的尝试，相关的研究也有不少，因此本文尝试做一个简单的综述，来简单看看这篇论文及其相关的研究。
〇、背景：建模（表面、体积） &amp;amp; 渲染 众所周知，计算机图形学中一个长期研究目标就是将虚拟的世界尽可能的渲染的真实。这里面包括了三个方面：
建模：通过表面建模、曲面建模等方式，将真实世界中的场景在虚拟世界中还原出来 渲染：按照物理中光照的规律，将虚拟世界中建好的模型绘制成人眼可见的画面 动画：通过仿真等方式，模拟出物体真实的运动轨迹等，使得动画看起来更加自然 NeRF 及相关工作所尝试解决的，主要是建模与渲染部分，也就是重建。建模的本质，其实是构造出一个空间中描述物体的函数：传统的建模大多采用显式的表示，比如曲线、曲面等等，或是球体、长方体；而近年来，随着神经网络的发展，有人提出能否使用神经网络来表示这一函数，毕竟神经网络本质上就是一个隐式函数，只不过其形式更加复杂、表示能力也更强。
在三维建模中，两个非常重要的通用建模方式是表面建模和体积建模：表面建模是通过描述表面曲面的方式构建模型，而体积建模则是通过描述空间点（体素）的方式构建模型；在表面建模里没有三维实体，实体只是闭合表面；在体积建模里没有二维表面，表面只是很薄的体素。学界在神经网络建模方面，也进行了类似的尝试，即使用神经网络来表示曲面（神经隐式曲面）和使用神经网络表示体积（神经隐式体积）。基于这两个大的思想，人们逐渐设计出各式各样的网络，并得到了越来越好的效果。
当然，建模之后，如果不能够进行渲染是没有意义的，因此如何高效地渲染出这些隐式表示的模型，也是学术界非常热门的话题。
一、序章：神经隐式曲面 1.1 基于分类的网络 第一大类的尝试，就是使用神经网络来表示曲面（Neural Implicit Surfaces）。前面提到，对于一个物体，实际上就是一个闭合的曲面，因此最直白的表示方法，就是给空间中的点进行分类，标记它在曲面内、还是曲面外。
Occupancy networks 和 IM-Net 都是基于这一思想的，两者主要是网络内部结构上不同，但是输入都是一个特征向量和一个空间点坐标，输出都是一个布尔值：在曲面内或在曲面外。下图是 IM-Net 的网络结构，以作示例：
另外还有将纹理特征一并结合的网络，如 PIFu：它除了编码了每个点是 inside 还是 outside，还将每个点的颜色信息也通过网络编码，从而实现了完整的高分辨率的着装人体数字化重建。
1.2 基于回归的网络 使用分类模型进行的表面建模确实是一个非常大的创新，但是一个很大的缺点就是这个模型所表示的函数并不可导——它不是连续的，毕竟物体内外这一输出本身就决定了函数的值域是一个离散的二值。因此，人们尝试使用一个连续的表示方式：有符号距离场，也就是大名鼎鼎的 SDF。
SDF 的定义很简单，其数值就是空间中的一个点距离曲面最近的距离，而符号表示其在闭合曲面的内部还是外部。这样通过一个有符号数，就将两个信息一起编码进去了，并且得到了一个在空间上可导的量。
SDF 的形式化定义如下：
DeepSDF 那么这样一个函数，非常自然的想到使用神经网络的 regression 进行解决，这也是 DeepSDF 的主要思想 —— 将一个描述物体形状特征的 Code 和空间坐标一并放入网络，然后输出该点的 SDF，从而实现利用深度网络重建一系列同类的物体。
值得关注的一点是，这个特征 Code 的特征是利用 Auto-decoder （注意不是 Auto-encoder）优化提炼的，作者们称之为 Encoder-less Learning，因为他们觉得 encoder 在推导的时候并没有被用到，所以不如不要，实际的重建效果也是非常的好，感觉是个非常有意思的想法。
DeepSDF 的诞生彻底引爆了这个领域，此后涌现出了大量相关的工作，如达摩院的 Curriculum DeepSDF 以及伯克利的 Extending DeepSDF，DeepSDF 本身也成为了不少工作的 baseline。</description>
      <content:encoded><![CDATA[<p>2020 年，在 CV/CG 界，一篇叫做 NeRF 的论文爆火，“只需要输入少量静态图片，就能做到多视角的逼真3D效果。”但是实际上，在这篇论文之前，学术界已经有不少这方面的尝试，相关的研究也有不少，因此本文尝试做一个简单的综述，来简单看看这篇论文及其相关的研究。</p>
<h2 id="背景建模表面体积--渲染">〇、背景：建模（表面、体积） &amp; 渲染</h2>
<p>众所周知，计算机图形学中一个长期研究目标就是将虚拟的世界尽可能的渲染的真实。这里面包括了三个方面：</p>
<ol>
<li><strong>建模</strong>：通过表面建模、曲面建模等方式，将真实世界中的场景在虚拟世界中还原出来</li>
<li><strong>渲染</strong>：按照物理中光照的规律，将虚拟世界中建好的模型绘制成人眼可见的画面</li>
<li><strong>动画</strong>：通过仿真等方式，模拟出物体真实的运动轨迹等，使得动画看起来更加自然</li>
</ol>
<p>NeRF 及相关工作所尝试解决的，主要是建模与渲染部分，也就是重建。建模的本质，其实是构造出一个空间中描述物体的<strong>函数</strong>：传统的建模大多采用显式的表示，比如曲线、曲面等等，或是球体、长方体；而近年来，随着神经网络的发展，有人提出能否<strong>使用神经网络来表示这一函数</strong>，毕竟神经网络本质上就是一个隐式函数，只不过其形式更加复杂、表示能力也更强。</p>
<p>在三维建模中，两个非常重要的通用建模方式是表面建模和体积建模：表面建模是通过描述表面曲面的方式构建模型，而体积建模则是通过描述空间点（体素）的方式构建模型；在表面建模里没有三维实体，实体只是闭合表面；在体积建模里没有二维表面，表面只是很薄的体素。学界在神经网络建模方面，也进行了类似的尝试，即使用神经网络来表示曲面（<strong>神经隐式曲面</strong>）和使用神经网络表示体积（<strong>神经隐式体积</strong>）。基于这两个大的思想，人们逐渐设计出各式各样的网络，并得到了越来越好的效果。</p>
<p>当然，建模之后，如果不能够进行渲染是没有意义的，因此如何高效地渲染出这些隐式表示的模型，也是学术界非常热门的话题。</p>
<h2 id="一序章神经隐式曲面">一、序章：神经隐式曲面</h2>
<h3 id="11-基于分类的网络">1.1 基于分类的网络</h3>
<p>第一大类的尝试，就是使用神经网络来表示曲面（Neural Implicit Surfaces）。前面提到，对于一个物体，实际上就是一个闭合的曲面，因此最直白的表示方法，就是给空间中的点进行分类，标记它在曲面内、还是曲面外。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/ON-teaser.png" alt="Occupancy as a learned classifier"  />
</p>
<p><strong>Occupancy networks</strong> 和 <strong>IM-Net</strong> 都是基于这一思想的，两者主要是网络内部结构上不同，但是输入都是一个特征向量和一个空间点坐标，输出都是一个布尔值：在曲面内或在曲面外。下图是 IM-Net 的网络结构，以作示例：</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222182017395.png" alt="image-20210222182017395"  />
</p>
<p>另外还有将纹理特征一并结合的网络，如 PIFu：它除了编码了每个点是 inside 还是 outside，还将每个点的颜色信息也通过网络编码，从而实现了完整的高分辨率的着装人体数字化重建。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222193033452.png" alt="image-20210222193033452"  />
</p>
<h3 id="12-基于回归的网络">1.2 基于回归的网络</h3>
<p>使用分类模型进行的表面建模确实是一个非常大的创新，但是一个很大的缺点就是这个模型所表示的函数并不可导——它不是连续的，毕竟物体内外这一输出本身就决定了函数的值域是一个离散的二值。因此，人们尝试使用一个连续的表示方式：有符号距离场，也就是大名鼎鼎的 SDF。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/DeepSDF.png" alt="The Stanford bunny rendered through a learned signed distance function (SDF)"  />
</p>
<p>SDF 的定义很简单，其数值就是空间中的一个点距离曲面最近的距离，而符号表示其在闭合曲面的内部还是外部。这样通过一个有符号数，就将两个信息一起编码进去了，并且得到了一个在空间上可导的量。</p>
<p>SDF 的形式化定义如下：</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/equation.svg" alt="equation"  />
</p>
<h4 id="deepsdf">DeepSDF</h4>
<p>那么这样一个函数，非常自然的想到使用神经网络的 regression 进行解决，这也是 <strong>DeepSDF</strong> 的主要思想 —— 将一个描述物体形状特征的 Code 和空间坐标一并放入网络，然后输出该点的 SDF，从而实现利用深度网络重建一系列同类的物体。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222201532556.png" alt="image-20210222201532556"  />
</p>
<p>值得关注的一点是，这个特征 Code 的特征是利用 Auto-decoder （注意不是 Auto-encoder）优化提炼的，作者们称之为 Encoder-less Learning，因为他们觉得 encoder 在推导的时候并没有被用到，所以不如不要，实际的重建效果也是非常的好，感觉是个非常有意思的想法。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222202136185.png" alt="image-20210222202136185"  />
</p>
<p>DeepSDF 的诞生彻底引爆了这个领域，此后涌现出了大量相关的工作，如达摩院的 Curriculum DeepSDF 以及伯克利的 Extending DeepSDF，DeepSDF 本身也成为了不少工作的 baseline。</p>
<h4 id="overfit-sdf">Overfit SDF</h4>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/network.png" alt="network"  />
</p>
<p>根据全局逼近定理（Universal Approximation Theory），一个具有充分多隐节点和采用任何激活函数的三层前馈神经网络能以任意精度逼近任何一个连续函数，因此我们其实可以直接对采样到的离散的 SDF 数据进行过拟合——即借助外部的 latent code，直接把物体的形状编码进网络的权重，一个网络对应一个物体即可。这就是 <strong>Overfit-SDF</strong> 的思想。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222230728553.png" alt="image-20210222230728553"  />
</p>
<p>相比于 DeepSDF，Overfit-SDF 面对观察角度的变化能够获得更加鲁棒的重建效果，如下图。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222230941628.png" alt="image-20210222230941628"  />
</p>
<h3 id="13-渲染">1.3 渲染</h3>
<p>对于隐式表示，一般来说常见的渲染方式是两种：<strong>方块遍历</strong>（<strong>marching cube</strong>）和<strong>光线步进</strong>（<strong>ray marching</strong>）。也有地方把 ray marching 称为 sphere tracing，细想想确实很形象，如下图。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/raymarching2.png" alt="raymarching2"  />
</p>
<p>实际上两者都是在从隐式表示中，采样表面的信息。个人认为相比起 marching cube，光线步进更能展现出这些 SDF 模型的连续性。</p>
<h4 id="131-加速">1.3.1 加速</h4>
<p>但是由于前面的这些模型的网络往往层数比较深，再加上使用了 ray marching，渲染的过程不可避免的会很慢，因此 <strong>Neural Geometric Level of Detail</strong> 这篇文章提出降低网络的深度，使用简单的一个感知机来对不同的细节层次进行自适应拟合，从而达到实时渲染的效果。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222234838118.png" alt="image-20210222234838118"  />
</p>
<p>这个工作首先使用稀疏体素八叉树（<strong>Sparse Voxel Octree, SVO</strong>）对物体的几何特征进行编码—— SVO 的不同层次实际也编码了细节的不同层次，即 <strong>LOD</strong> (Level of Detail)，而每个角点上的体素（可以先理解为一个数据结构，后面会解释）储存了局部的表面特征；在采样的时候，首先找到对应的几个体素，然后将其中储存的特征经过插值获得一个连续的特征，最后通过一个很简单的多层感知机来从这个综合出来的特征解码得到 SDF 的值。整个流程如下图所示：</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222233643015.png" alt="image-20210222233643015"  />
</p>
<p>这个工作可以说是又快又好，既提高了渲染精度，又加快了渲染速度，还简化了网络结构。也许它也在启发着我们，真的复杂的就一定是最好的吗？有时候将一些已知的先验信息加入，往往可以达到事半功倍的效果。</p>
<h2 id="二爆发神经隐式体积">二、爆发：神经隐式体积</h2>
<h3 id="21-体素渲染">2.1 体素渲染</h3>
<p>但是在解释这些基于体积的建模工作之前，让我们来先看看这里的体素渲染到底是怎么回事。</p>
<blockquote>
<p>事实上，关于体素渲染和体积渲染的定义已经因为很多商业游戏公司的宣传和炒作变得模糊和混淆，因此这里介绍的体素渲染是针对这两篇论文中采用的建模方法而言的。</p>
</blockquote>
<p>所谓体素（Volume Pixel），就是体积像素的简称，与像素类似，每个体素包含了空间中一个最小分割单位中的信息，比如图片中的像素包含的是该点的 RGB 值，而体素则可以包含一个点的不透光性或者密度等。</p>
<p>基于体素的模型认为三维物体是由很多个体素构成的，每个体素包含自己的颜色和密度（或是不透明度）。那么在观察一个物体的时候，只要沿着光线方向进行积分，就可以得到这一角度所观察到的物体的最终颜色，如下图所示。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/5e6942d2a99a2eb319075849_volume-rendering-diagram.jpg" alt="Diagram shows a basic diagram of volume rendering using single-pass GPU ray casting."  />
</p>
<p>实际上仔细想想这个设定其实还有点道理，比如一个物体切的无限薄，其终将呈现出半透明乃至透明的状态。而且通过这种方式建模，天然的解决了半透明物体的重建问题。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222220827030.png" alt="image-20210222220827030"  />
</p>
<p>第一个将体积渲染与神经网络相结合的是 <strong>Neural Volumes</strong>，它将一个三维的物体，拆解为一个个体素——每个体素包含了密度信息和颜色信息，这样就得到了一个基于体素的三维物体表示方法；接下来，使用一个 Encoder + Decoder 对输入的多个角度的图片进行编码和采样，就得到了一个能够重建特定物体的 latent code，并且可以从中解码出一个三维空间的 volume；接下来，在这个 volume 中使用 ray marching 进行积分采样，即可得到重建的结果。</p>
<p>训练的时候，Neural Volumes 是直接进行端到端的训练的，即输入多个角度的图像，然后拿对应角度重建的图像计算 loss。</p>
<p>“Neural Volumes 的成功很大程度上归功于这种‘半透明’的几何表示方式，因为它使得梯度能够沿着射线的积分分散开来，进而更加容易收敛到一个较好的结果上”，一篇引用了 Neural Volumes 的论文如是说。</p>
<h3 id="22-nerf">2.2 NeRF</h3>
<p><strong>NeRF</strong> 是神经辐射场（Neural Radiance Fields）的缩写，它彻底引爆了整个领域。</p>
<p>本质上来说，NeRF 与 DeepSDF 的网络结构差不多，但是与 DeepSDF 所回归的 SDF 函数不同，NeRF 回归的是体素的密度和颜色，也就是说，NeRF 将体素信息视作了一个函数，然后使用神经网络去拟合它。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222223550599.png" alt="image-20210222223550599"  />
</p>
<p>值得注意的是，NeRF 的输入是一个 5 维的向量——它包含了一个体素的位置  和观察它的角度 （所以采集的时候还要带上相机的外参），这是因为按照图形学中物体材质相关的理论，一个物体的同一位置（同一材质）在不同的光照角度之下确实会观察到不同的颜色；NeRF 考虑到了这一点，因此直接把材质信息也直接包含了进去；当然，场景的光照信息也被不可避免的烘焙了进去。</p>
<p>另外为了解决高频信息丢失的问题，比如特定角度下的高光（如下图），NeRF 对 voxel position 和 view position 都进行了 embedding，也就是把他们映射到一个高维空间中，进而大大增强了模型对于细节的重建能力。</p>
<p><img loading="lazy" src="/2021-02-24_NeRF.assets/image-20210222224836594.png" alt="image-20210222224836594"  />
</p>
<p>另外 NeRF 的渲染中还利用到了重要性采样，也就是先对一条光线上大致的密度分布进行估计，然后按照这个估计的密度曲线进行重要性采样，这样可以加快采样时收敛的速度。</p>
<p>NeRF 以其简单的原理、简单的模型、超好的重建效果引爆了整个学术界，大量基于 NeRF 的改进工作，如 Relighting、性能提升、动态场景等都被悉数完成，而大量基于 NeRF 的应用也在涌现，比如人物肖像重建、形状重建、场景组合、姿态估计等。这些 NeRF-style 的工作无一不证明着 neural volume 的巨大潜力。</p>
<h2 id="三展望">三、展望</h2>
<p>近年来，采用神经网络来代替传统表示的工作越来越多，如 SLAM 中接替 Kinect Fusion 的 Neural Fusion，再如使用网络表示纹理的 Neural Textures，还有上文的各种工作。神经网络黑箱的属性正在逐渐退去，其函数的本质正在被逐步挖掘。充分利用网络的拟合能力，并融入足够的先验知识，可能才是解锁神经网络潜力的钥匙。</p>
<p>另一方面，neural volume 相关的工作中，人们最终还是不可避免的尝试恢复表面本身，体素会不会只是一种目前效果最好的中间表示？LOD 的工作是否意味着未来人们会重新回归到基于 SDF 的方法？这些问题的答案从目前看来还是未知的。</p>
<p>令人振奋的是，这些工作基本都是近年完成的；也许随着研究的深入、资金的投入，这些问题很快就会得到解答。这一切的一切，都非常值得我们期待。</p>
<blockquote>
<h2 id="参考文献">参考文献</h2>
<ol>
<li>NeRF Explosion 2020 <a href="https://dellaert.github.io/NeRF/">https://dellaert.github.io/NeRF/</a></li>
<li>Tewari, Ayush, Ohad Fried, Justus Thies, Vincent Sitzmann, Stephen Lombardi, Kalyan Sunkavalli, Ricardo Martin-Brualla, et al. “State of the Art on Neural Rendering.” <em>ArXiv:2004.03805 [Cs]</em>, April 8, 2020. <a href="http://arxiv.org/abs/2004.03805">http://arxiv.org/abs/2004.03805</a>.</li>
<li>Mildenhall, Ben, Pratul P. Srinivasan, Matthew Tancik, Jonathan T. Barron, Ravi Ramamoorthi, and Ren Ng. “NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis.” <em>ArXiv:2003.08934 [Cs]</em>, August 3, 2020. <a href="http://arxiv.org/abs/2003.08934">http://arxiv.org/abs/2003.08934</a>.</li>
<li>Williams, Jon. “Occupancy Networks: Learning 3D Reconstruction in Function Space | Autonomous Vision.” Max Planck Institute for Intelligent Systems. Accessed February 22, 2021. <a href="https://is.mpg.de">https://is.mpg.de</a>.</li>
<li>Saito, Shunsuke, Zeng Huang, Ryota Natsume, Shigeo Morishima, Angjoo Kanazawa, and Hao Li. 2019. “PIFu: Pixel-Aligned Implicit Function for High-Resolution Clothed Human Digitization.” ArXiv.org. 2019. <a href="https://arxiv.org/abs/1905.05172">https://arxiv.org/abs/1905.05172</a>.</li>
<li>Park, Jeong Joon, Peter Florence, Julian Straub, Richard Newcombe, and Steven Lovegrove. 2019. “DeepSDF: Learning Continuous Signed Distance Functions for Shape Representation.” <em>Thecvf.com</em>, 165–74. <a href="https://openaccess.thecvf.com/content_CVPR_2019/html/Park_DeepSDF_Learning_Continuous_Signed_Distance_Functions_for_Shape_Representation_CVPR_2019_paper.html">https://openaccess.thecvf.com/content_CVPR_2019/html/Park_DeepSDF_Learning_Continuous_Signed_Distance_Functions_for_Shape_Representation_CVPR_2019_paper.html</a>.</li>
<li>Davies, Thomas, Derek Nowrouzezahrai, and Alec Jacobson. “On the Effectiveness of Weight-Encoded Neural Implicit 3D Shapes.” <em>ArXiv:2009.09808 [Cs]</em>, January 17, 2021. <a href="http://arxiv.org/abs/2009.09808">http://arxiv.org/abs/2009.09808</a>.</li>
<li>Takikawa, Towaki, Joey Litalien, Kangxue Yin, Karsten Kreis, Charles Loop, Derek Nowrouzezahrai, Alec Jacobson, Morgan McGuire, and Sanja Fidler. “Neural Geometric Level of Detail: Real-Time Rendering with Implicit 3D Shapes.” <em>ArXiv:2101.10994 [Cs]</em>, January 26, 2021. <a href="http://arxiv.org/abs/2101.10994">http://arxiv.org/abs/2101.10994</a>.</li>
<li>“Neural Volumes: Learning Dynamic Renderable Volumes from Images - Facebook Research.” 2019. Facebook Research. 2019. <a href="https://research.fb.com/publications/neural-volumes-learning-dynamic-renderable-volumes-from-images/">https://research.fb.com/publications/neural-volumes-learning-dynamic-renderable-volumes-from-images/</a>.</li>
<li>Mildenhall, Ben, Srinivasan, Pratul P, Matthew Tancik, Jonathan T Barron, Ravi Ramamoorthi, and Ren Ng. 2020. “NeRF: Representing Scenes as Neural Radiance Fields for View Synthesis.” ArXiv.org. 2020. <a href="https://arxiv.org/abs/2003.08934">https://arxiv.org/abs/2003.08934</a>.</li>
<li>Weder, Silvan, Johannes L. Schönberger, Marc Pollefeys, and Martin R. Oswald. “NeuralFusion: Online Depth Fusion in Latent Space.” <em>ArXiv:2011.14791 [Cs]</em>, November 30, 2020. <a href="http://arxiv.org/abs/2011.14791">http://arxiv.org/abs/2011.14791</a>.</li>
<li>Thies, Justus, Michael Zollhöfer, and Matthias Nießner. “Deferred Neural Rendering: Image Synthesis Using Neural Textures.” <em>ArXiv:1904.12356 [Cs]</em>, April 28, 2019. <a href="http://arxiv.org/abs/1904.12356">http://arxiv.org/abs/1904.12356</a>.</li>
</ol>
</blockquote>
]]></content:encoded>
    </item>
  </channel>
</rss>
