← Journal

把一张照片变成 3D:SHARP 高斯泼溅实验

用 Apple 的 SHARP 模型从单张照片推理出 3D 高斯泼溅场景,压缩后塞进博客,用自己写的 WebGL2 查看器在浏览器里转着看。

一张普通的照片里,其实藏着”这个场景大概长什么样”的全部线索——人眼扫一下就能脑补出纵深。现在模型也可以:SHARP(Apple 开源)能从单张静态图直接推理出一个 3D 高斯泼溅(3D Gaussian Splatting)场景。

我把整条流水线跑通了,成果放在这里,可以直接玩:

👉 进入「照片 → 3D 实验室」 —— 拖动旋转、滚轮缩放,随时切回原图对照。

整条流水线

照片 (2.8MB jpg)
  → SHARP 推理(RTX 4080,约 3 秒)
  → 3DGS 点云 .ply(118 万个高斯点,63MB)
  → 剪枝 + 量化(自定义 16 字节/点格式,9MB)
  → WebGL2 实时渲染(无三方库)

几个值得记录的点:

1. 生成在另一台机器上跑

开发机的显卡跑不动 SHARP 固定的 1536² 推理分辨率,所以生成这步扔给了家里的主力机(RTX 4080 SUPER)。走 WireGuard 的 SSH 远程执行,一条命令出图:

sharp.exe predict -i inputs -o outputs -c sharp_2572gikvuh.pt

16G 显存下单张推理只要 3 秒,反而是把 63MB 的结果拖回开发机花的时间最久——中转服务器的带宽才是瓶颈。

2. 63MB 塞不进网页,得压

SHARP 输出的 .ply 每个高斯点占 56 字节(位置、颜色、不透明度、尺度、旋转都是 float32)。对网页来说 63MB 完全不可接受,于是做了两层压缩:

  • 剪枝:先丢掉不透明度低于 2% 的点,再按”不透明度 × 投影面积”的贡献度排序,只保留最重要的 60 万个点;
  • 量化:位置压成 16 位(相对包围盒),尺度、颜色压成 8 位,旋转四元数压成 3 个 8 位分量——每点 16 字节。

最终 9MB,肉眼几乎看不出差别。

3. 查看器是手写的

浏览器端没有用 three.js 之类的库,直接写 WebGL2:每个高斯点画一个实例化四边形,顶点着色器里把 3D 协方差投影成屏幕上的 2D 椭圆(EWA splatting),片元按高斯衰减做半透明混合。混合顺序靠 16 位计数排序维护——60 万个点排一次不到 10 毫秒,只在视角转动超过阈值时才重排。

一些观察

  • 单图推理的 3D 在小幅度视角变化下非常唬人,侧到一定角度就会露出”纸片感”和拉丝——毕竟照片没拍到的地方全靠模型脑补,所以查看器里我限制了旋转范围。
  • 有纵深层次的场景(街景、房间)效果远好于平面构图。
  • 这套流水线是可复用的:以后任何照片丢进主力机的 original-images 文件夹,几分钟内就能变成博客里一个可交互的 3D 场景。

之后打算换上自己拍的照片再生成几个场景(当前示例图来自 wallhaven,版权归原作者,仅作技术演示),也许做成一个小相册页。