AI 创作开放麦 · 2026-08
口袋里的暗房
小胶片(Little Film)—— 把 iPhone 对准胶卷负片,取景框里直接看到照片。
负片 ⇌ 正片 · 同一张胶片 · 模型实时转换
John · 机器学习工程师 · 胶片爱好者 · 约 12 分钟
旧故事 · 2024
当时,它只是一段命令行脚本
2024 · CLI
$ python -m filmcvt negatives/ positives/ --use-wbnn
输入一个文件夹 → 逐张裁切、反相、校色 → 输出 JPG
算法已经能跑,但每次都要回到电脑,用命令处理一整个文件夹。
2026 · 从脚本到 App
现在,可以直接在手机上完成
01定位并拉直胶片
在透视、反光与强背光下找到四角,再映射成标准画幅。
02负片反相
逐像素计算 1 − x,把负片的明暗关系翻回来。
03色彩校正
WBNN 预测 3×11 多项式变换,去除橙色片基与色偏。
第一步 · 找框 · 先亲手对一次
四个角,确定一次透视变换
把青色框套到画幅上——四角与矩阵互相确定;拖动任意一边,另一边同步 ↓
FrameNet 只预测四角;拖动四角时,页面实时反解 H。
找框是学习问题 · 拉直是几何问题
网络找四角,几何求 H
FrameNet → 四角坐标 | 四组点对应 → H → 拉直
1 · 四组具体坐标p₁(0.10,0.10)↔q₁(0,0)p₂(0.82,0.16)↔q₂(1,0)p₃(0.72,0.84)↔q₃(1,1)p₄(0.18,0.76)↔q₄(0,1)
2 · 定义 H,再逐组代入
p₁0.10a+0.10b+c = 00.10d+0.10e+f = 0
p₂0.82a+0.16b+c = 0.82g+0.16h+10.82d+0.16e+f = 0
p₃0.72a+0.84b+c = 0.72g+0.84h+10.72d+0.84e+f = 0.72g+0.84h+1
p₄0.18a+0.76b+c = 00.18d+0.76e+f = 0.18g+0.76h+1
3 · 页面实际求得 H————————1.000
同一组数驱动上面的求解与下面的网格动画;App 中由 CIPerspectiveCorrection 完成对应步骤。
数据 · 自己拍
让标注免费
- 常规做法:先拍照,再一张张手工画框——画一百张要一晚上;
- 反过来:先画框,再拍照——App 随机给一个框,你把胶片对进去拍,框就是现成的标签;
- 拍了 100 张——一杯水的功夫。
数据 · 一张变一百张
增强:已知答案的考试
训练时把每张采集的照片随机换窗口、转角度、调亮度、加噪声和假反光——变换是我们施加的,所以角点标签跟着同一个变换走,等于免费多拍了一百倍。
同一批照片增强后的训练样本 · 绿框 = 跟随变换的标签 · 每个 batch 都是新的
冷知识
「把数据揉一揉再让网络做题」是大模型的同款配方——遮住词猜词,揉皱图猜角。自监督学习的通用套路。
微调与验证
FrameNet:2.6 px
20未参与训练的真实图像
2.6 px平均角点坐标误差
8.3 px最差样本
≈ 1.6%相对 161 px 画幅宽度
尺度示意 · 绿 = 真值 · 红 = 按 2.6 px 偏移绘制 · 右侧放大 4×
合成数据 + 真实手机图像微调约 30 分钟;指标在 224 × 224 输入空间计算。
第二步 · 反相
逐像素,把明暗翻回来
一个像素 = (R, G, B) // 红、绿、蓝三个 0–1 的数
(R′, G′, B′) = (1−R, 1−G, 1−B) // 三个通道分别反相
在任意一边移动鼠标选一个像素,两边同步显示它的三个数 ↓
第二步 · 反相 · 我们试过的
四种反相,四个答案
同一张负片,四种「负转正该怎么算」。x线 = 按 sRGB 公式还原成线性光,片基估计为 (211,127,88);四张只调了曝光,没做任何白平衡。
① 码值补数x′ = 1 − x发灰发青,黑压不下去
② 线性域补数x′线 = 片基线 − x线整体偏橙,暗部塌掉
③ 除以片基x′线 = 片基线 ÷ x线黑是黑了,蓝得更狠
④ 密度域 + γx′线 = (x线 ÷ 片基线)−1/γ层次最好,颜色最离谱
四种都能把明暗翻过来,没有一种能把颜色带回来。
差别不只是「偏色」——它们连偏的方向都不一样,说明剩下的不是一个乘法,而是一整条形状未知的曲线。
于是我们不再猜这条曲线:反相就用最简单的 ①,剩下的交给数据。
第三步 · 白平衡 · 你来试试
你来当调色师
图上移动鼠标选像素(两边同一位置);上下拖动矩阵里的数字,整张图跟着变 ↓
9 个数还只是「线性」调色,已经拧不明白了——那么,交给网络?
第三步 · 白平衡 · 让网络拧
33 个旋钮,网络来拧
φ(r,g,b) = [ r, g, b, r², g², b², rg, rb, gb, rgb, 1 ]ᵀ
[R′,G′,B′]ᵀ = M3×11 · φ(r,g,b) ← M 的 33 个数由网络给出
多项式核出自 Afifi & Brown, “When Color Constancy Goes Wrong” (WB-sRGB), CVPR 2019 · §3.3
一张图先变成 11 张「基图」 · 输出的每个通道 = 它们的线性组合(权重就是 M 的一行)
- 为什么不只用 3×3?错误白平衡已经经过相机的非线性色彩、色调与 Gamma;论文比较多种映射后,这个 11 项多项式核效果最好。
白平衡 · 数据与目标
WBNN:像素级 MSE
约 50 万张正常照片组成干净目标 y;随机色偏生成输入 x = D(y)。
同一张干净图 y,可以生成许多种带色偏输入 x
通道乘法 0.5–1.5
通道偏置 0–0.5
Gamma 0.8–1.2
全局缩放 0.8–1.0
合起来
完整的一条链
- 两个模型 + 两步无参数算法,30 FPS 跑在手机上;
- 三步全部可单独开关——出问题时看中间结果,比看代码快。
从协作到产品
两天做出原型,再把它变成小胶片
模型解决“看见胶片”,产品设计解决“什么时候拍、能不能反悔、照片去哪里”。
对准 · ALIGN
停稳 · HOLD
揭晓 · REVEAL
D1先让旧研究跑起来。
复活两年前的代码,转换 Core ML,装进 iPhone,再接通实时取景与自动找框。
D2再用真实手机画面修正它。
合成训练、采集 100 张灯箱照片、微调到 2.6 px,让模型适应现场反光与曝光。
UX最后把能力变成可理解的体验。
充能提示让快门可预期,轻晃可以取消;拍完先揭晓,只有用户确认才保存。
AI 编程助手PyTorchCore MLSwiftUI
下一步
谢谢,来试试小胶片
去反光模型
更高分辨率
App Store
把灯箱,变成一间小暗房。
产品与幻灯片:filmcvt.enhuiz.com
← → 翻页