
1. 为什么折腾到 tachi 与 SBS 这条路上这件事其实是被逼出来的。手头有几个 VR 盒子头显也入了门但每次想找点片源看看就头疼。网上能下到的 3D 资源基本还是十年前那批分辨率低、码率差有些还带着莫名其妙的 logo。而新出的电影、游戏实况、综艺几乎全部是普通 2D 片源拿头显看也就是放大了的 2D 画面跟窝在沙发上看电视没有本质区别。于是我开始琢磨能不能在手机上把 2D 内容实时变成 3D 再喂给头显或者裸眼 3D 设备看。翻了一圈市面上的方案各自的短板都很明显。先列一下我当时比较过的几条路线离线 2D 转 3D 工具像 DVDFab 那类软件转换效果确实可以做到很精细但一部电影要转几个小时甚至一宿转完硬盘还要多占好几个 G。最要命的是它不实时等转换完成我连看片的兴致都没了。直接下载成品 3D 片源资源少更新慢很多是重编码的翻录版画质损失严重。遇到想看的片没有 3D 版等于白搭。播放器自带的假 3D 滤镜手机上某些播放器有仿 3D效果其实就是给画面边缘加了点模糊和偏移看起来像纸片人贴图毫无空间感。专用的实时 2D 转 3D 方案例如 GitHub 上 tachi 这类项目用端侧推理做单目深度估计再通过视差渲染输出 SBSSide-by-Side画面。这条路实现难度最大但一旦跑通任何 2D 视频、相机画面、游戏画面都能随时变成 3D。我最终就是被 tachi 这几个字给勾住的。它解决了我最痛的点不挑片源打开就能用而且是实时的。SBS 则是最稳妥的输出格式——几乎所有的 VR 盒子、VR 头显、裸眼 3D 手机屏幕都认它甚至电视上切换到左右 3D模式也能直接显示。它在技术上没有那么花哨但兼容性就是它的最大价值。如果你也是那种手里的设备吃灰太久、不甘心的人或者本身就是对端侧 AI 落地感兴趣的开发者这篇文章应该能给你一些参考。我尽量把原理和实操都讲透。2. 先把核心原理理清楚视差是假的但效果是真的很多人一听2D 转 3D第一反应是这玩意儿不靠谱吧一张图怎么可能凭空多出深度。这个怀疑是有道理的因为整个过程确实不是复原真实的三维场景而是根据图像内容推断出哪块近、哪块远再用这个推断结果生成一对带有视差的左右眼视图骗过我们的大脑。2.1 人眼立体感的来源这事情比想象中简单人眼感知立体核心靠的是两个眼睛看同一物体时因为视角不同而产生的视差。你把手指伸到眼前闭上左眼用右眼看再闭上右眼用左眼看会发现手指相对背景的位置变了这个变化就是视差。大脑把左右眼的两幅画面叠加起来根据差异大小判断距离。所以 2D 转 3D 的本质就一句话制造出合理的左右眼视差。只要左右眼视图的视差关系符合物体的前后位置关系大脑就会自动产生深度感。至于这个深度是从哪算出来的大脑其实并不关心。2.2 从一张图算出深度单目深度估计模型在做什么关键在于怎么知道画面里谁远谁近。传统做法是双目摄像头、结构光或者 ToF 传感器但手机上普遍只有一个摄像头只能靠单目深度估计。单目深度估计的思路听起来有点反直觉没有第二个视角也没有主动照射纯靠一张彩色图去猜每个像素的相对距离。它凭什么能猜出来靠的是经验。模型在大量带深度标注的数据集上训练学习了大量环境先验——比如远处的山是灰蓝色的、近处的地面纹理更清楚、同一个物体表面的颜色通常连续、物体之间的遮挡关系可以提供前后信息等等。推理时模型把这些先验综合起来输出一张深度图每个像素值代表该位置离相机的大致远近。tachi 底层用的就是这类基于深度学习的单目深度估计模型。常见的开源模型有 MiDaS、ZoeDepth、DPT 等其中 MiDaS 系列因为对移动端算力的要求相对宽松被很多端侧实时项目拿来用。MiDaS 的核心特点是在多数据集上联合训练对户外、室内、人物、风景都有不错的泛化能力。2.3 深度图怎么变成左右眼视图DIBR 渲染链路拿到了深度图不等于就完成了 3D 转换。深度图只是告诉你谁深谁浅要生成左右眼视图还需要一步叫DIBRDepth-Image-Based Rendering基于深度图像的渲染的操作。DIBR 的原理可以理解为假设我们要模拟左眼的位置那么画面里的近处物体应该相对向右偏移因为左眼看近物时它偏右侧反过来模拟右眼时近处物体应该向左偏移。偏移量的大小由该像素的深度值决定——越近的物体偏移越大越远的物体偏移越小远景甚至偏移几乎为零。实际实现时一般流程是把深度图转换为视差图视差值的公式是视差 基线距离 × 焦距 / 深度。这个公式是从双目匹配的原理推过来的你可以简单类比成你左右移动脑袋去看同一个物体移动距离越大、离得越近的东西在视野里跳得越多。以原始 2D 图像为基准逐像素地按照视差图向左或向右挪动像素位置。左右眼各自产生一张新视角的图。但这里马上会遇到一个实际问题像素挪动之后原来被前景遮挡的背景区域会出现空洞有点像我们把贴纸从墙上撕下来墙上留出空白。处理空洞有几招邻域采样填充直接用空洞周围的像素填进去适合空洞不大的情况。边缘扩展拉伸把边缘像素向外复制适合背景纹理简单的画面。更彻底的方案先做背景修复或者在渲染时根据深度做多层背景插值。实时场景下基本只能选第一种或第二种因为计算量有限。实际效果上只要空洞不集中在人眼最关注的物体边缘观感是完全可接受的。2.4 SBS 结构左右眼画面怎么并排放进一个画面SBS 全称 Side-by-Side就是左右眼画面并排放在同一个视频帧里的格式。一个 1920×1080 的 SBS 画面左半部分是左眼视图右半部分是右眼视图。更细分有全宽 SBS和半宽 SBS全宽 SBS左右眼各自用了完整的 1920×1080 分辨率总画面是 3840×1080需要播放设备具备 4K 级别的解码能力。半宽 SBS左右眼各自是 960×1080整个画面是 1920×1080观看时再被拉伸到全屏。这是移动端最常用的格式节省带宽和渲染压力。tachi 的 SBS 实现方案里半宽 SBS 基本是默认选项。原因很简单手机解码全宽 SBS 压力极大帧率稳不住而半宽 SBS 虽然横向分辨率砍半但经过头显镜片放大后实际观感损失并不至于不可接受。尤其是对动态画面人眼的注意力更多在空间感和流畅度上而不是静态解析力。3. tachi 的 SBS 实时实现链路拆解这一章是整篇博文的重头戏。前面那些原理如果算道那这一步就是术具体怎么在手机上把一条完整的实时管线搭起来。tachi 的整体架构大概是下面这个链路源帧获取相机 / 视频解码 → 帧缩放与格式转换 → 端侧深度推理 → 深度图后处理 → DIBR 视差渲染 → SBS 合成 → 显示输出这中间每一步都有不少坑我一个个拆开讲。3.1 端侧推理框架选型NCNN vs ONNX Runtime vs MNNtachi 在模型推理层选了 NCNN这个选择我实际用下来认为是对的。当时我在 NCNN、ONNX Runtime Mobile、MNN 三个框架之间反复横跳最后发现 NCNN 更适合这个场景大概有这几个原因移动端算子覆盖全单目深度估计模型里常见的卷积、上采样、激活函数、残差连接NCNN 做了大量 ARM 汇编级优化在手机 CPU 上跑得很快。尤其是 4×4、2×2 的上采样NCNN 有专门的优化实现。部署体积小整个 NCNN 核心库加在一起只有几百 KB 级别对安装在手机上的 App 来说非常友好。量化工具链成熟NCNN 提供了从.pt、.onnx转换的完整工具链也支持 FP16、INT8 量化。当然 ONNX Runtime Mobile 也有它的强大之处尤其是对 GPU 算子的支持和跨平台一致性更好但内存占用比 NCNN 多一些。MNN 的推理速度在部分芯片上能跟 NCNN 打成平手但生态和文档相对 NCNN 还是差一点。如果你是第一次接触这个领域我建议CPU 推理为主就选 NCNN想利用 GPU 加速就仔细考虑 Vulkan 或者 OpenCL 后端不要一上来就追求多框架支持先跑通一条链路比什么都重要。3.2 模型压缩与量化让深度模型跑在手机算力上单目深度估计模型原始版本体积不小比如 MiDaS 的大模型 DPT 系列单次推理在桌面级 GPU 上也要几十到上百毫秒放到手机上直接卡成幻灯片。tachi 的思路是引入轻量级 backbone 的 MiDaS 变体比如用 MobileNet 系列的变体模型把输入分辨率控制在比较低的水平比如 256×256再配合量化压缩。我实际试验下来FP16 量化是实时处理的最佳平衡点。INT8 量化虽然能进一步提速但深度图的边缘会明显发糊后续 DIBR 时容易产生边缘锯齿和天空撕裂一样的伪影。FP16 在主流手机上都能由 CPU 直接运算或者在 GPU/NPU 上获得不错的加速。模型推理分辨率的选择也很有讲究。原始相机画面如果是 1080p你完全不需要在 1080p 上做逐像素深度推理那算力要求太高了。通常的做法是把原始帧缩小到 320×240 或者 480×270 左右在这个低分辨率上做深度估计再把深度图上采样回需要的渲染尺寸作为渲染阶段坐标偏移的依据。深度图分辨率低于原始画面反而有好处深度本身的精度不需要特别高低分辨率图自带一定的平滑效果能抑制深度图的高频噪声。3.3 视频取流与帧同步MediaCodec 和相机两条入口tachi 需要同时支持视频文件/流播放和相机实时画面两类来源这两条路的取帧方式完全不同。先看视频场景。手机上的视频解码基本都是通过 MediaCodec 做的而 MediaCodec 最典型的接入方式有两种一是直接输出到 Surface 显示二是配合SurfaceTexture把解码帧作为 OpenGL 纹理做后处理。tachi 选择的是第二种MediaCodec 解码输出到 SurfaceTexture然后渲染线程通过updateTexImage()获取最新纹理再交给后续管线。这里有个大坑解码帧率并不是均匀的尤其在高码率视频或者硬解能力不足的机型上帧与帧之间的间隔波动很大。如果你的处理管线过于繁琐很容易出现一帧还没处理完下一帧就已经到了的情况。典型的解决办法是维护一个帧缓冲池渲染线程和解码线程解耦解码线程只管往缓冲池里塞帧渲染线程空闲时再取最新帧处理。中间允许丢旧帧保证实时性优先。再看相机场景。相机的取流走 Camera2 APItachi 的做法是使用ImageReader或者ProcessingSurface方式获取 YUV 帧。如果 Camera2 的输出帧率跟不上处理速度同样会出现缓冲区堆积。更常见的问题是相机参数变化对推理结果的干扰自动对焦、曝光变化、白平衡漂移都会让深度推理输出的深度图产生跳变。我建议在做相机类内容时尽量固定对焦模式为连续或者干脆锁定在无穷远把曝光时间限制在一个相对稳定的区间。这样深度估计的输入视频帧特征比较稳定输出深度图不会频繁跳变。3.4 DIBR 实现用 OpenGL ES Shader 把视差渲染做到接近零拷贝深度推理出来的深度图要参与渲染最忌讳的是把深度图从 GPU 内存拷回 CPU做完偏移计算再拷回 GPU那带宽和延迟直接劝退。正确的做法是把 DIBR 整个搬到 GPU用 Shader 做像素级处理。以 OpenGL ES 为例核心思路是把原始彩色帧作为采样纹理u_colorTexture把深度图作为另一个采样纹理u_depthTexture顶点着色器不做什么特殊操作片元着色器里对每个像素做一次视差偏移采样。片元着色器的核心逻辑大致如下半宽 SBS 渲染场景// 片元着色器为左眼/右眼生成偏移采样坐标 precision mediump float; uniform sampler2D u_colorTexture; uniform sampler2D u_depthTexture; uniform float u_baseOffset; // 基础偏移强度可调用于控制视差强度 uniform int u_eye; // 0 表示左眼1 表示右眼 varying vec2 v_texCoord; void main() { // 采样当前像素的深度值normalize到 [0,1]越近深度值越小具体映射视模型而定 float depth texture2D(u_depthTexture, v_texCoord).r; // 根据左右眼方向计算偏移方向 float direction (u_eye 0) ? 0.5 : -0.5; // 近处物体偏移大远处物体偏移小 float offset (1.0 - depth) * u_baseOffset * direction; // 半宽 SBS 下左右眼的采样坐标要映射到原始画面的一半区域 vec2 colorCoord v_texCoord; // 这里 v_texCoord 在 SBS 输出帧里的坐标范围是 [0,1]但左右两半各对应原画面 // 因此需要把 SBS 的半区域坐标映射回原图坐标 vec2 st vec2(colorCoord.x * 2.0 - float(u_eye), colorCoord.y); // 加上视差偏移并采样 vec2 finalCoord st vec2(offset, 0.0); // 处理边缘越界用边缘像素填充 finalCoord clamp(finalCoord, 0.0, 1.0); gl_FragColor texture2D(u_colorTexture, finalCoord); }这段 Shader 做了三件事读取深度、按眼别计算偏移方向、把 SBS 输出坐标映射回原图。实际工程里还要加上u_baseOffset的调节这个参数对观感影响极大后面我会专门说。当然这只是一个最简版本的 DIBR。更精细的实现会考虑空洞填充、边缘羽化和深度图平滑这些可以在片元着色器里加几行逻辑但性能成本要自己掂量。在 tachi 的实际代码里合成 SBS 的阶段是利用 FBO帧缓冲对象把左右眼图像分别渲染到输出画面的左半和右半区域。整个过程在 GPU 内部完成不需要 CPU 介入因此称为近零拷贝。3.5 系统管线串联从源帧到 SBS 输出的路径整理把前面几节串起来整个处理流是这样的源帧输入MediaCodec 或者 Camera2 把帧作为 GL 纹理送进来。预处理通过渲染到 FBO 的方式把纹理缩放到模型输入尺寸同时做 YUV → RGBA 转换如果源是 YUV。深度推理把预处理后的纹理数据上传到 NCNN 推理框架通常会走 NCNN 的 GPU 后端需要做纹理到 Tensor 的转换输出深度图。深度后处理把深度图上采样到渲染分辨率必要时做一次高斯模糊去噪。DIBR 与 SBS 合成用片元着色器分别渲染左眼和右眼视图输出到屏幕或者录制缓冲。线程模型上推荐渲染线程 推理线程 取流线程三线程分离。取流线程只负责与相机/解码器交互推理线程独立持有模型实例处理最新帧渲染线程负责 GL 资源管理在垂直同步信号到来时绘制最终画面。推理线程的输出跟渲染线程之间通过共享纹理或共享显存完成尽量少用锁。这里要说一个很实际的经验整个链路最容易被忽略的是 GL 上下文和线程绑定问题。OpenGL ES 的上下文默认不能在多线程同时使用如果推理线程要从 GPU 拿到纹理数据需要用到eglMakeCurrent做双上下文共享纹理这个配置不对会让你在部分手机上崩溃而且是偶发崩溃非常难排查。4. 帧率与温度的博弈性能实测和调参心得光说不练假把式。tachi 跑起来之后我在几台不同定位的手机上做了实测数据和结论比任何理论都更真实。4.1 不同手机芯平台上的帧率、延迟、温度、功耗数据测试条件统一为1080p 视频源半宽 SBS 输出模型输入分辨率 256×192FP16 量化深度图输出分辨率 480×270。测试结果如下手机平台深度推理耗时整链路渲染耗时稳定帧率发热状态30分钟后旗舰骁龙 8 Gen2约 18ms约 45ms稳定 30fps峰值能跑到 40fps温热约 40℃中端骁龙 778G约 35ms约 70ms25-30fps 波动明显发热约 44℃中低端天玑 900约 60ms约 90ms15-20fps烫手开始降频旧款麒麟 990约 50ms约 80ms20-25fps发热明显偶发掉帧需要强调的是这个成绩是关闭手机系统省电模式、调高电源策略后的结果。如果默认模式下运行天玑 900 那档基本没法看帧率会掉到 10fps 以下。结论很直观中端平台推荐把推理分辨率降到 192×144输出深度图再上采样这样可以换来大约 15-20% 的帧率提升。旗舰机也不要盲目开高因为手机散热是持续输出的瓶颈不是瞬时算力。4.2 关键参数矩阵怎么配置才能不卡我在 tachi 里做了参数可配置化这里给出一份我反复验证过的参数组合场景模型输入深度图分辨率推理间隔输出分辨率备注看视频旗舰256×192480×270每帧推理1080p SBS流畅立体感强看视频中端192×144480×270每2帧推理1080p SBS保留深度连续性相机实时旗舰256×192480×270每帧推理1080p SBS注意锁定曝光相机实时中端192×144320×180每2帧推理720p SBS优先保帧率裸眼3D手机256×192480×270每帧推理根据屏幕像素映射需要逐机型适配注意每 2 帧推理这种策略深度估计不必每帧都做可以在两次深度推理之间采用上一帧深度图 当前帧彩色图来渲染画面运动不快时几乎看不出区别。对于动态场景比如镜头快速晃动深度图滞后会带来明显的边缘错位这时候就得强制回到每帧推理。4.3 延迟优化的几个细碎技巧延迟是实时处理的关键指标。从源帧到最终显示的延迟我实测下来主要消耗在三个环节深度推理本身是大头所以选择的模型体积和输入分辨率影响最大。纹理上传是隐藏拖后腿选手。从 GL 纹理到 NCNN Tensor 的转换如果不使用 GPU 后端NCNN Vulkan 或 OpenCL回读 CPU 会很耗时。tachi 默认走 GPU 后端这个坑能避开。渲染线程与垂直同步的同步等待。如果一帧渲染刚好错过 vsync 窗口需要多等一整个刷新周期约 16ms。解决办法是使用三重缓冲或者干脆让渲染线程以固定 60fps 的节奏主动等待而不要被动等 vsync。还有一个很多人没想到的小技巧延迟一帧渲染。意思是不要追求当前帧立即出结果而是让渲染线程用上一帧的深度图渲染等待推理线程输出当前帧深度图。这样虽然从绝对时间上延迟没有变化但避免了推理线程和渲染线程互相等待产生的抖动实际体感更顺滑。4.4 发热降频策略长看不烫手怎么做到实时推理持续运转发热是绕不开的。头显本就是贴脸设备发烫体验会很难受。我折腾下来的做法分三层限制帧率上限默认锁 30fps不要开放 60fps。30fps 配合 SBS 的立体效果观感已经足够流畅。动态分辨率调整在系统温度达到 41℃ 时把模型输入从 256×192 降到 192×144达到 43℃ 时再把深度图分辨率降一档同时把推理间隔从每帧改成每 2 帧。这套策略在 tachi 里可以用温控模块配置。边缘算力调停让深度推理的优先级低于渲染线程渲染线程永不阻塞。如果推理赶不上就用上一帧深度渲染这样画面永远是流畅的只是立体感会偶尔滞后一点。5. 上了真机之后3D 效果调优与踩坑实录参数和链路都通了设备连上头显或者让裸眼 3D 屏亮起来真正的玄学阶段才开始。这章写的全是我自己踩过的坑每一个都能单独写一篇长文了。5.1 3D 效果不明显的罪魁祸首视差强度和基线我第一次跑通 tachi 时戴上头显后的第一反应是这跟原视频有什么区别画面虽然确实是 SBS左眼和右眼的内容也确实是不同视角但立体感几乎为零。问题出在视差强度设置上。DIBR 渲染时的u_baseOffset也就是基线距离的等效值被我设得太小了左右眼画面差异过弱大脑自然感知不到深度。把基础偏移调大之后立体感立刻出来了但紧接着又是一个新问题画面中近处物体的边缘开始出现明显重影看久了犯晕。这个平衡点需要反复试我个人的经验是先暂停视频看静止画面的边缘重影情况。如果前景和背景边缘在左右眼视图里错位超过大约 1.5% 的屏幕宽度观感就危险了。把基础偏移调整到边缘看起来依然干净但你明显能感觉到屏幕里前后有层次的状态就差不多了。不同内容需要不同的强度。大场景航拍强度可以适当调高拍人像特写强度要调低否则人脸边缘会非常容易裂开。5.2 画面闪烁、深度跳变时域平滑与后处理深度模型是逐帧独立推理的没有时间记忆所以同一个像素在当前帧被判为近下一帧可能因为光照变化、物体轻微移动就变成了远。这种深度图抖动在连续播放时表现为物体边缘的呼吸感和闪烁纹。我的解决办法是给深度图加一个时域平滑滤波维护一个上一帧的深度纹理当前帧深度纹理与上一帧深度纹理按比例混合比如 7:3 或 8:2。混合比例很关键比例太大运动物体会出现拖影太小闪烁压制不住。实测下来对于绝大多数视频内容7:3 的混合比例比较稳妥。如果镜头运动剧烈可以把比例动态调低但不要低于 5:5。空间维度上深度图在输入 DIBR 之前做一个高斯模糊也会有奇效。因为深度图不需要非常精细的边缘模糊之后反而能减少边缘的锯齿感。5.3 Camera2 取流的那些坑相机实时 2D 转 3D是 tachi 最让人兴奋也最折磨人的场景。我踩过的坑按严重程度排序如下预览尺寸与显示尺寸不一致很多手机的后置主摄默认输出 4:3 比例但屏幕是 16:9 甚至 20:9直接做 SBS 拉伸会把人脸拉变形。需要先通过 Crop 或 CenterInside 方式裁剪到目标比例再送进处理管线。自动对焦与自动曝光对深度推理的干扰相机聚焦位置变化、曝光幅度跳变都会让深度图的绝对深度分布发生剧烈变化。后面做时域平滑时这些变化会造成整个画面忽远忽近的呼吸现象。解决办法是尽量固定对焦和曝光参数或者对深度图做逐帧归一化后再使用。横竖屏旋转手机旋转时相机传感器方向与纹理坐标系方向可能错位导致深度图方向与画面方向不一致出来的 SBS 左右眼变成上下错位。处理时一定要根据传感器旋转角度在采样阶段对深度图做相应旋转。5.4 MediaCodec 播放流程的时序坑视频播放场景下MediaCodec 的输出时机是帧率不稳定的根源。tachi 的管线设计里取流线程与渲染线程是完全解耦的这自然带来了更平滑的体验但也引入了一个我一开始没预料到的坑杀掉解码线程后MediaCodec 会卡在 release 上。在切换视频源或者退出播放时如果 MediaCodec 还处于CodecState.SUBMITTED状态release 操作会导致主线程卡死好几秒。后来我总结出的正确流程是先停止渲染线程、再通知解码线程退出、在解码线程内部调用stop()和release()。顺序反了基本都要踩一次 ANRApplication Not Responding。另一个坑是断了声画同步。当 SBS 处理管线让画面延迟了大约 100ms 之后音频和视频会明显不同步嘴型对不上。tachi 的做法是把音频也按固定延迟推后播放通过AudioTrack的setPlaybackPositionUpdateListener做缓冲控制或者在播放器层面利用投递队列强制 audio sink 跟随 video 的节奏。但这里没有万能解因为不同播放器的MediaCodec和AudioTrack行为略有差异。5.5 不同观看设备的适配裸眼 3D 手机、VR 盒子、头显SBS 虽然兼容性好但不同设备对 SBS 画面的处理方式并不完全一样必须对症下药。VR 盒子手机插进去的那种最省心只要把输出画面切成半宽 SBS让屏幕横屏全屏播放左右两半正好对应两只眼睛。这里唯一要注意的是手机屏的尺寸和视场角不同尺寸的盒子对画面中心距的设定不太一样但一般不需要调整。VR 头显一体机串联手机主流头显支持 SBS 输入模式但有的只支持左右眼各一个 4K 视频流的推流方式而不是单画面 SBS。如果出现画面左右颠倒或者上下颠倒先检查头显设置里左右眼映射的选项不要在 tachi 里硬转方向。裸眼 3D 手机这个是最麻烦的。裸眼 3D 屏幕带有柱状透镜它的像素映射是固定的而且不同型号的手机透镜间距不同。tachi 虽然能输出 SBS但要让画面在裸眼 3D 屏上准确呈现出立体效果需要在输出时按屏幕像素映射关系做二次采样——左右眼内容必须被对齐到透镜下的精确像素位置。否则要么立体感消失要么出现奇怪的摩尔纹。6. 后续想继续做的事tachi 这个项目走到现在2D 转 3D 实时 SBS 的核心链路已经跑通了。但离我理想中的状态还有一段距离我给自己列了几个后续方向也分享给有意折腾的朋友用 Vulkan 替代 OpenGL ESVulkan 可以让渲染线程与推理线程更好地共享资源利用 subpass 特性减少内存带宽消耗延迟应该还能再压掉 10-20ms。给深度估计加入光流信息目前深度图是逐帧独立的时域平滑只能缓解抖动如果有一份轻量级的光流信息去校正深度传播运动物体的立体感会明显稳定很多。支持更多输出格式除了 SBS上下格式Top-Bottom和帧交替格式Frame Sequential在一些快门式 3D 眼镜和 3D 电视上有需求。做格式封装并不难难的是不同输出设备下的同步信号适配。把处理能力抽成通用 SDKtachi 的核心管线其实可以模块化成独立的2D 转 3D 实时引擎这样无论是第三方播放器还是相机 App 都能用复用推广价值更大。说到最后我最想分享的经验是2D 转 3D 这个项目真正的难关不在模型或者算法本身而在系统管线的整体优化。模型推理稍微慢一点可以有各种手段弥补但管线设计不合理比如取流卡顿、线程互相等待、纹理频繁拷贝那才是直接把体验击穿的关键问题。这也是我折腾完 tachi 之后最大的感悟。如果你也打算在自己手机上复现这条链路建议先别急着追求画质先用最低分辨率跑通全链路确认每一环都无损流畅再逐步提高参数。过程中如果遇到深度图边缘闪烁、画面发晕、帧率不稳的问题多半能从这篇文章里找到对应的解决思路。祝你们玩得开心。