想象一位记忆画师,他受邀为一尊雕塑绘制画像。他不能把雕塑搬走,只能绕着它慢慢走,从东、南、西、北、高处、低处,各画一张速写。训练结束的那一刻,他闭上眼睛,在脑中把几十张速写融成一尊可以转动的立体模型。从此,无论你请他画出哪个角度——哪怕是拍摄时从未站过的地方——他都能挥笔而就,连雕塑背面的纹路都分毫不差。这位画师,就是神经辐射场(NeRF)。它是机器人智能与学习领域的一双“透视眼”:机器人用摄像头绕物体转一圈,学到一尊“密度雕塑”,抓取前能看清透明杯子的轮廓,导航时能分辨哪面墙会挡路。本文以记忆画师的视角,带你走一遍NeRF从原理到机器人抓取与导航应用的完整旅程。
学会NeRF,等于给机器人装上能从任意角度“看见”物体的眼睛,它直接支撑抓取规划、导航避障等核心机器人任务,是机器人感知算法工程师绕不开的关键技能。
可视化演示
演示神经辐射场NeRF从多视角图像重建三维场景:光线采样、体积渲染与新视角合成,用于机器人抓取规划与导航感知。
本节配有交互动效(进入视口后自动加载,约 3KB)。
光线采样 相机 采样点 r(t)=o+td 沿光线采样场景空间点
重建核心原理
记忆画师开始工作前,养成了一个习惯:每画一张速写,都在本子上记两笔——自己站在哪个位置,视线朝向哪个方向。因为雕塑上同一片衣褶,从正面看是高光,从侧面看是阴影,不记下“看到的角度”,速写就失去了立体感。
NeRF(神经辐射场)同样把“站在哪里、看向哪里”当成输入。它是一个用神经网络实现的函数 $F_{\Theta}$:输入空间位置 $(x, y, z)$ 和视线方向 $(\theta, \phi)$,输出这个点的颜色 $\mathbf{c}$ 和密度 $\sigma$。这五个数字,就是画师本子上的那两行记录。
密度 $\sigma$ 是 NeRF 最特别的输出,它回答“这个位置有没有实体”:在物体表面附近密度高,在空旷处几乎为零。把场景中每个位置都“问一遍”,就得到整个场景的隐式表示——不直接存点云或网格,而是把整个雕塑“压缩”进神经网络的参数里。训练网络的过程,就是画师反复对照速写、修正脑内模型的过程。
不过画师立刻发现一个毛病:脑中模型的大轮廓很清晰,细花纹却总是模模糊糊。这就要说到一个让画笔变细的技巧——位置编码。
- 位置输入告诉画师“你在触摸雕塑的哪一处”,是三维重建的坐标基础。
- 方向输入告诉画师“你正从哪个角度观察”,同一位置因反光、镜面会呈现不同颜色。
- 颜色输出返回该点的 RGB 颜色值,对应画师笔下的颜料。
- 密度输出返回该点“有多实心”,数值越大越接近实体表面。
位置编码技巧
画师有个烦恼:大块面的明暗、雕塑的整体轮廓,他画得又快又准;可一旦碰上衣褶上的细纹、发丝的走向,笔下的线条就“糊”成一片。这并非手抖,而是人眼天生偏爱大面积、平滑的明暗过渡,对高频的小细节不敏感。
神经网络也有一样的“低频偏置”:直接输入 $(x, y, z)$ 这样光滑的坐标,网络会倾向于学出平滑函数,边缘、纹理等高频信息被自动磨平。NeRF 论文的作者发现,把坐标先做一次“调频”再喂给网络,细节就能保住。
这个调频操作就是位置编码。它用一组频率成倍递增的正弦、余弦函数,把一维坐标 $p$ 展开成高维向量,就像给画师配了一套从粗到细的画笔:低频函数负责大体轮廓,高频函数负责精细纹路。
频带总数 $L$ 就像画师笔盒里的笔的规格。经典 NeRF 对位置取 $L=10$、对方向取 $L=4$ 是经验平衡点:太多会把照片噪点也描进去,太少则细节尽失。对机器人场景,调 $L$ 往往比调网络深度更见效。
笔尖调好了,画师终于要动笔——可眼前这个从未站过的角度,颜色到底该怎么落?答案藏在体渲染方程里。
- 原始坐标连续坐标是位置编码的“素颜”输入,先原样保留一份。
- 频率倍增频率从 $2^0$ 到 $2^{L-1}$ 成倍爬升,相当于笔尖从粗到细排列。
- 正余弦配对同一频率同时用正弦和余弦记录,保留相位信息,避免位置偏移失真。
体渲染方程
画师从一个从没站过的地方,从眼睛出发朝雕塑“射”出一道视线。视线穿过空气、掠过表面,沿途每一小段空间都有可能留下一抹颜色。体渲染方程要回答的正是:这一路小段的颜色,该如何累加成画布上那个像素?
规则很朴素:先看光线走到这里还剩多少“力气”(透射率 $T$),再看这一小段的密度 $\sigma$ 有多大、颜色 $\mathbf{c}$ 是什么,三者相乘,便是这一小段的贡献。密度高的表面贡献最大,空气的贡献趋近于零。
更关键的是透射率——前面已经有实体挡住,后面的颜色就被“吃掉”了。正是这个机制,让 NeRF 能自然地表达遮挡关系:后面的物体看不见了,是因为光线已经被前面“用光”。
实际实现中,积分被离散成求和:在光线上采几百个点,逐点计算再累加。画师每次挥笔,都在做一次“沿视线的颜料结算”——这也是后面所有加速技巧要优化的对象。
画师画得太慢了。如果每个像素都从光线起点一直问到终点,一幅画要磨上大半天,必须想点加速的办法。
- 光线参数化把视线写成一个射线方程,$t$ 代表从起点走了多远。
- 透射率函数从起点走到当前点,沿途密度的累积会衰减剩余光线,这就是“还剩多少力气”。
- 颜色积分把每一小段的贡献在整条光线上积分,得到该像素最终颜色。
训练加速方法
画师的改进办法很朴素——先画速写,找重点,再精修。NeRF 也采用“粗-细”双网络策略:粗网络先在光线上均匀采样,快速摸清密度的大致分布;根据粗网络输出的分布,把后续采样集中到密度高、变化大的区域,再交给细网络精修。采样点花在了刀刃上。
两条网络的损失一起优化:粗网络的渲染结果和细网络的渲染结果都要逼近真实照片。粗的学轮廓,细的抠细节,误差共同反向传播,画师的“手感”在一次次的对比中变得越来越准。
除了粗细双网络,后来的哈希网格编码把画纸预先打好格子:空间位置落在哪个格子直接查表,把庞大的网络查询换成紧凑的查表运算,训练与渲染都快了几个数量级。对要部署到机器人上的场景,“加速三板斧”是落地的前置条件。
画师学成出师,朋友突然央求:“从正上方看一眼吧!”——这个角度拍摄时从没站过。他能画出来吗?
- 粗网络渲染粗网络沿光线均匀采样,输出低成本的粗略颜色。
- 细网络渲染细网络沿粗网络推荐的重要区域密集采样,输出精细颜色。
- 双路损失两路渲染都与真实像素颜色求平方误差并相加,作为总损失一起反传。
新视角合成
画师愣了一下,随即从容落笔。新视角合成的原理就藏在体渲染方程里:任意给出一条新视线,沿它做一次“透明度 + 密度 + 颜色”的积分,就得到对应像素的颜色。因为场景知识被编码在网络权重中,任何连续角度都能渲染,且相邻视角的画面平滑一致,不会像平面插值那样“翻车”。
合成质量需要用指标检验。最常用的是 SSIM(结构相似度),它不只是比像素差多少,而是从亮度、对比度、结构三个维度综合评价两张图的相似程度,就像一个挑剔的评委同时看三份考卷。
对机器人来说,新视角合成等于“没拍过的角度也能预先演练”:抓取前先在脑内把抓手转到侧面看一眼会不会碰到邻件,导航前先俯瞰走廊确认宽度。画师的神奇能力,成了机器人的预判能力。
画师的本领终于轮到实战——机器人要去抓一个透明玻璃杯。这能行吗?
- 亮度均值先比较两张图各自的平均亮度,这是基础分。
- 方差与协方差再看各自的纹理丰富程度,以及两者变化是否同步。
- 综合评分三项组合成 0 到 1 之间的分数,越接近 1 表示两图越相似。
抓取规划应用
传统 RGB-D 相机遇到透明物体常常抓瞎:深度传感器看不见玻璃,表面像被“挖空”。可画师的密度模型不在乎透不透明——只要那个位置确实有实体,密度就会诚实地指向表面。NeRF 因此成了抓取透明、反光物体的利器。
抓取流程分为三步:先用多视角照片训练 NeRF 得到密度场;再用等值面提取算法把密度场转成机器人可用的表面;最后在表面上评估候选抓取位姿——哪里适合下爪、哪里是把手。其中等值面提取的关键是选阈值 $\tau$:把“密度恰好等于 $\tau$”的所有空间点连起来,就是物体表面。Marching Cubes 就是最常用的“连线”算法。
密度场表面比点云更“完整”:杯柄的弧线、碗沿的薄边都连续存在。机器人把“看见的形状”翻译成“下爪的姿势”,透明物体不再是抓取噩梦——画师的“手感”,就是密度场。
抓取只是第一步。机器人要在一整栋陌生房子里走动,画师还得把房子画成一张“可以摸的地图”。
- 密度查询在任意空间位置查询网络输出的密度值,判断实心程度。
- 阈值判定选一个密度阈值 $\tau$ 作为“实 / 空”的分界线。
- 等值面集合所有密度恰等于阈值的点构成一张隐式表面,可交给 Marching Cubes 转成网格。
导航感知融合
画师这次接了个大活:把一栋陌生房子画成一张“可以摸的地图”,标清楚哪面墙能靠、哪张桌子会挡路、哪扇门刚好够机器人通过。传统视觉 SLAM 常输出稀疏特征点:它能说“这里有面墙”,却说不清墙面到底离机器人多近。
NeRF 的密度场给出的是连续占据信息:任意查询一个空间点,都能回答“这里有实体还是空着”。这种稠密表示天然适合碰撞检测与路径规划,机器人可以把整张地图当作一个“连续实心度查询器”来用。
导航中机器人还在不断移动,相机位姿必须同步优化。可微渲染提供了一个优雅闭环:用当前猜测的位姿渲染一幅图,跟相机真实拍到的图比较,差异对位姿求梯度,梯度引导位姿越猜越准——“画得越像,位姿越对”。
真实家庭环境总有人走动、门会开合,这是 NeRF 导航的前沿挑战。多模态融合成为出路:触觉、深度、IMU 等信息与视觉密度场互相校验,动态部分标记为“可变化”,静态部分用于精细建图——画师的地图从此有了“动”与“静”的分层。
- 相机位姿机器人的位置和朝向属于三维刚体变换,既含旋转也含平移。
- 渲染预测给定位姿后,用 NeRF 沿观测光线渲染出预测图像。
- 最小化差异找到最优位姿,使预测图像与观测图像的平方误差和最小。
AI 应用场景
仓储机器人的透明物体抓取
阶段:感知与决策
解决的问题:传统 RGB-D 相机依赖主动光的反射,遇到透明玻璃、金属反光表面会出现深度空洞,抓取时“一把抓空”。NeRF 从多视角图像重建连续密度场,不依赖单点反射特性,能稳定还原透明物体的表面,再结合等值面提取与抓取位姿评估,显著提升抓取成功率。
具体案例:某电商分拣仓的机械臂面对一箱透明玻璃杯。感知团队绕货架拍摄 40 张多视角照片,离线训练 NeRF 后提取杯子表面网格;上料时机械臂先在 NeRF 场景中做“虚拟试抓”,确认无碰撞后再执行实体抓取。实测抓取成功率从 71% 提升到 93%,换型时只需重拍照片重训模型。
家庭服务机器人的稠密建图与避障
阶段:环境感知与地图构建
解决的问题:传统 V-SLAM 输出稀疏特征点地图,无法回答“透明的茶几玻璃到底挡不挡路”这类细粒度问题。NeRF 提供连续密度场,任意空间点的占据状态可查询,为 A*、RRT 等路径规划算法生成稠密代价地图,让机器人在玻璃、镜面、暗光场景下也能安全移动。
具体案例:扫地机器人在客厅游走,绕家具采集多视角图像构建 NeRF 稠密场。当它靠近透明茶几时,密度场明确指出玻璃表面的位置,机器人选择绕行;门被打开后,系统通过多帧增量更新密度场,把“开出的门洞”标记为可通行区域。
机器人训练数据的仿真生成
阶段:训练数据合成
解决的问题:机器人强化学习需要大量“观察-动作”数据,纯仿真环境和真实世界存在传感器差异(Sim-to-Real gap)。NeRF 重建的真实场景可以作为渲染背景:在 NeRF 场景中自由变换视角,生成逼真的新视角图像,补充真实相机分布的训练样本。
具体案例:机械臂抓取训练中,团队用 NeRF 重建了真实分拣台面,再在 NeRF 渲染的背景下合成 10 万张带标注的抓取样本,与真实采集数据混合训练视觉抓取网络,仿真到实物的迁移成功率提升了约 12%。
Python 演示
"""微型NeRF:从多视角"光线"学习二维圆盘场景,再合成新视角。""" import numpy as np def scene(x, y): """真实场景:以原点为中心的发光圆盘。""" if x * x + y * y < 0.6: return np.array([1.0, 0.4, 0.3]) return np.zeros(3) def pos_enc(points, L=4): """位置编码:把坐标映射到多组正弦余弦特征。""" feats = [points] for k in range(L): feats.append(np.sin(2 ** k * np.pi * points)) feats.append(np.cos(2 ** k * np.pi * points)) return np.concatenate(feats, axis=-1) def sample_rays(num_views, pts_per_ray): """从多个相机视角出发,沿视线均匀采样。""" pts, cols = [], [] for v in range(num_views): ang = 2 * np.pi * v / num_views origin = np.array([2.0 * np.cos(ang), 2.0 * np.sin(ang)]) for t in np.linspace(0.05, 0.95, pts_per_ray): p = origin + t * (-origin) pts.append(p) cols.append(scene(p[0], p[1])) return np.array(pts), np.array(cols) class TinyNeRF: """两层全连接网络:编码特征 -> 颜色。""" def __init__(self, in_dim, hidden=24): self.w1 = np.random.randn(in_dim, hidden) * 0.4 self.b1 = np.zeros(hidden) self.w2 = np.random.randn(hidden, 3) * 0.4 self.b2 = np.zeros(3) def forward(self, x): h = np.maximum(x @ self.w1 + self.b1, 0) return h @ self.w2 + self.b2 # 训练数据:24个视角,每视角32个采样点X, C_true = sample_rays(num_views=24, pts_per_ray=32)X_enc = pos_enc(X, L=4)net = TinyNeRF(X_enc.shape[1])lr = 0.02 for epoch in range(1000): h = np.maximum(X_enc @ net.w1 + net.b1, 0) C_pred = h @ net.w2 + net.b2 err = C_pred - C_true loss = np.mean(err ** 2) g2 = 2 * err / len(X) net.w2 -= lr * (h.T @ g2) net.b2 -= lr * g2.sum(axis=0) g1 = (g2 @ net.w2.T) * (h > 0) net.w1 -= lr * (X_enc.T @ g1) net.b1 -= lr * g1.sum(axis=0) if epoch % 200 == 0: print("epoch %d loss %.5f" % (epoch, loss)) # 新视角合成:选一个不在24个训练视角里的角度new_ang = 0.61origin = np.array([2.0 * np.cos(new_ang), 2.0 * np.sin(new_ang)])ray_t = np.linspace(0.05, 0.95, 100)ray_pts = origin + ray_t[:, None] * (-origin)ray_color = net.forward(pos_enc(ray_pts, L=4))real_color = np.mean([scene(p[0], p[1]) for p in ray_pts], axis=0)print("真实场景平均颜色:", np.round(real_color, 3))print("新视角渲染平均颜色:", np.round(np.mean(ray_color, axis=0), 3))
feats.append(np.sin(2 ** k * np.pi * points))位置编码的核心:高频正弦项补充坐标表达中的细节。origin = np.array([2.0 * np.cos(ang), 2.0 * np.sin(ang)])把相机放在圆周上,实现围绕场景的多视角采样。class TinyNeRF:用两层全连接网络充当记忆画师的“脑内模型”。h = np.maximum(X_enc @ net.w1 + net.b1, 0)ReLU 激活,让网络有能力表达非线性场景。g2 = 2 * err / len(X)输出层梯度,即均方误差对预测的导数。net.w2 -= lr * (h.T @ g2)梯度下降更新参数,画师的“脑内模型”逐渐被修正。ray_pts = origin + ray_t[:, None] * (-origin)新视角光线的采样点,沿视线从远到近排列。ray_color = net.forward(pos_enc(ray_pts, L=4))对整条光线做推理,合成未见角度的画面。
常见误区
误区“NeRF 是神经网络,输入一张照片应该就能输出 3D 模型吧?像超分辨率一样一拍就有。”
正解NeRF 的“重建”是对单个场景的逐场景拟合。它需要同一场景的多视角照片(通常数十到上百张)和对应相机位姿,通过反复比较渲染与真实照片来调整密度场。只给一张图,被遮挡区域的约束完全缺失,模型只能靠猜。跨场景单图重建属于 PixelNeRF 等泛化变体,是另一类模型。
为何常见:深度学习中“端到端、一张图出结果”的范式太深入人心,而 NeRF 的“场景专属拟合”范式常被忽略。
误区“NeRF 训练完,直接就能导出 STL 网格给机器人用。”
正解NeRF 输出的是隐式密度场——一个能回答“某点密度多少”的函数,而不是显式网格。要得到机器人抓取能用的 mesh,需要用 Marching Cubes 等算法按阈值提取等值面;或者直接在密度场上做抓取位姿搜索。“场”和“网格”之间隔着一道转换手续。
为何常见:演示视频常把重建结果渲染成“看起来像网格”的图,容易让人误以为模型本身输出的就是网格。
误区“反正高频细节重要,L 越大重建越精细,直接拉满!”
正解L 过大时,网络会去拟合照片里的传感器噪声和微小伪影,出现“过拟合噪点”;L 过小则边缘与纹理被磨平。经典 NeRF 对位置取 L=10、对方向取 L=4,是经验上的平衡点,实际场景要靠验证集来调。
为何常见:“参数越多能力越强”的直觉在缺少正则化时会失效,高频分量并非越多越好。
误区“NeRF 就是站在两张照片中间,把像素混合一下,对吧?”
正解像素插值只是在二维图像平面做混合,遇到视角变化导致的遮挡、视差就会露馅。NeRF 先把场景学成三维密度场,再沿任意新光线做体渲染积分,天然处理遮挡与视差,能生成大角度、连续变化的真实新视角。两者表面相似,机制完全不同。
为何常见:从最终效果看,两者都“生成了中间视角”,容易混淆 2D 图像域操作与 3D 场景域渲染。
误区“视频里 NeRF 渲染那么快,直接部署到机器人上做实时感知呗。”
正解标准 NeRF 训练要几十分钟到几小时,渲染一张图也要秒级,直接做实时导航会卡顿。实际部署常用 Instant-NGP 哈希编码、3D 高斯泼溅等加速方案,先把模型压缩优化,再配合轻量渲染器上机器人。距离嵌入式实时仍有距离。
为何常见:演示视频常加速播放或用高端 GPU,让人误以为开销很小。
面试题
Q1. NeRF训练最核心的输入数据是什么?
- A.大量普通照片无需标注
- B.多视角图像与相机位姿← 正确答案
- C.单张高清深度图像数据
- D.从离线生成的点云数据
答案:B。NeRF 需要同一场景从多个角度拍摄的照片,以及每张照片对应的相机位姿,训练时反复渲染并与实拍对照。单张照片缺少遮挡信息,点云和深度图也不是 NeRF 的标准输入。
Q2. 位置编码在NeRF中的主要作用是什么?
- A.压缩高维场景特征维度
- B.增强高频细节表达能力← 正确答案
- C.降低神经网络的模型参数量
- D.把渲染时间缩短为原来一半
答案:B。网络对低频信号更敏感,直接学习坐标会把边缘纹理磨平;位置编码用多组正弦余弦把坐标展开到高频空间,让细节能被表达。它不压缩维度,也不减少参数,更不直接加速渲染。
Q3. NeRF体渲染中,像素颜色主要由什么加权累积而成?
- A.表面反射率和环境光照
- B.光线各采样点的密度与颜色← 正确答案
- C.相机曝光与白平衡设置
- D.光线的起始位置与方向
答案:B。体渲染沿视线逐段计算“透射率 × 密度 × 颜色”再累加,得到像素颜色。密度高的表面贡献大,空气贡献小。反射率、曝光、光线位置都不是体渲染的加权项。
Q4. 粗网络与细网络配合使用的好处有哪些?
- A.粗网络快速分布初始采样点← 正确答案
- B.细网络聚焦高密度区域细化← 正确答案
- C.两个网络各自独立无需交互
- D.一定能把训练时间降为原来一半
答案:AB。粗网络先均匀采样摸清密度分布,细网络据此在表面附近密集采样,实现“重点区域多描几笔”。两网络必须配合传递采样分布信息,且提速效果因场景而异,谈不上“一定减半”。
Q5. 关于NeRF的新视角合成,正确的说法是?
- A.仅对两张图片做像素插值
- B.从隐式场渲染连续新视角← 正确答案
- C.只能预测训练视角的内容
- D.必须结合深度相机才能合成
答案:B。新视角合成是从学到的密度场出发,沿任意新视线做体渲染积分,能自然处理遮挡与视差,视角连续平滑。像素插值在二维平面混合、遇遮挡就失效;深度相机也不是必需。
Q6. 从NeRF密度场提取机器人可用的物体表面,常用方法是?
- A.从中密度阈值提取等值面← 正确答案
- B.把网格转换成神经网络的权重
- C.对多视角图像做特征匹配对齐
- D.用等值面细化光线重采样流程
答案:A。选一个密度阈值 τ,把所有“密度恰好等于 τ”的空间点连起来,就是物体的隐式表面,Marching Cubes 负责把表面转成网格。B、C、D 都不属于从密度场提取表面的操作。
Q7. 要判断NeRF重建场景中某点是否有物体,可以查询?
- A.该点颜色通道的数值大小
- B.该点的密度是否超过阈值← 正确答案
- C.该点距离相机的远近
- D.该点位置编码的向量维度
答案:B。密度就是对“这里有没有实体”的回答:超过阈值说明在物体表面或内部,接近零说明在空域。颜色、距离、编码维度都不能直接给出占据判断。
Q8. NeRF训练加速的常见方法包括?
- A.分层重要性采样策略← 正确答案
- B.哈希编码加速特征查询← 正确答案
- C.用位置编码替代全部网络
- D.仅在单一视角上重复训练
答案:AB。分层采样把算力集中到高密度区,哈希编码把空间网格映射到紧凑特征表、大幅减少网络查询,两者都是经典加速手段。位置编码替代不了网络,单视角训练会丢失三维信息。
Q9. NeRF新视角渲染误差关于相机位姿的梯度,可以直接用于?
- A.优化相机位姿与场景表示← 正确答案
- B.反向传播更新抓取扭矩控制
- C.直接合成激光雷达点云数据
- D.替代里程计进行轮速标定
答案:A。渲染图与观测图的差异对位姿求梯度,形成可微渲染闭环——不断调整位姿使渲染贴近观测,这正是基于 NeRF 的视觉定位思想。扭矩由控制层负责,激光雷达数据来自传感器,轮速标定与渲染梯度无关。
Q10. NeRF在机器人抓取中的典型流程包括?
- A.多视角拍摄重建物体形状← 正确答案
- B.从密度场提取物体表面← 正确答案
- C.直接输出末端执行器扭矩
- D.省略标定直接完成抓取定位
答案:AB。抓取链路中 NeRF 负责“重建形状 + 估计表面”,得到表面后才能规划抓取位姿。扭矩属于控制层输出,相机标定是输入位姿的前提,都不能被 NeRF 替代。