【免费下载链接】NegPy
Tool for processing film negatives.
NegPy 是一款专为胶片负片扫描打造的暗房级处理工具(Tool for processing film negatives)。为什么它不直接"一键反相",而是引入 H&D 曲线与 ISO-R 分级流水线?因为负片记录的是对数密度而非线性明暗,简单取反只会得到一张"反过来的负片"——发灰、发闷、层次尽失。本文带你深度解析这套负片处理的核心算法与完整流水线。
为什么简单反相会毁掉负片细节?
很多新手以为:负片 = 照片的镜像,取反像素就好。但扫描仪读到的其实是一组光透过率,NegPy 直接在线性 RGB(output_color=raw、gamma=1、统一白平衡)上工作,随后做对数转换:
- 密度是日志值:胶片密度 $D = \log_{10}(\text{参考透过率} / \text{实际透过率})$,负片的高光和阴影在胶片上是被"压缩"过的,直接反相无法还原这段压缩。
- 橙色蒙版不是全局色偏:彩色负片每个通道的橙蒙版浓度不同。NegPy 对每个通道独立做百分位定界(0.01%–99.99% 窗口)并拉伸到 [0,1],让橙色蒙版和片基色被各自"中和"掉,而不是用一张白卡颜色去猜。
- 打印需要曲线:暗房里放大机下的相纸天然带 toe(趾部)、直线段、shoulder(肩部)三段特性。NegPy 把这条曲线完整搬进了算法,反相只是"打印"的第一步。
一句话:NegPy 不是在"反相",而是在模拟一次暗房放大(详见 docs/PIPELINE.md 的 "The Print" 一节)。
暗房级H&D曲线:在密度空间里"打印"照片
🎞️ 这是整个引擎的心脏。归一化后的信号进入密度空间,经过一条非对称 toe-linear-shoulder 特性曲线:
- 中间是一段斜率为 $k$ 的直线(由 ISO-R 分级决定);
- toe(阴影端)软着陆到纸黑 $D_{max} = 2.3$;
- shoulder(高光端)软着陆到纸白 $D_{min} = 0.06$(Paper White Base 可关闭,退回 0);
- 两端都是softplus 软拐点,用
toe_sharpness_base/shoulder_sharpness_base控制膝盖锐度,而非硬截断——所以拉伸到界外的调子会被曲线"卷"回来,而不是直接死黑死白。
曲线核心计算(CPU 引擎,CPU/GPU/图表共用同一数据源):
v1 = d_min_eff + logaddexp(0, a_hl * (v - d_min_eff)) / a_hl # shoulder → 纸白 res = d_max_eff - logaddexp(0, a_sh * (d_max_eff - v1)) / a_sh # toe → 纸黑源码:negpy/features/exposure/logic.py#L465-L495,常数定义见 negpy/features/exposure/models.py#L144-L165
最后一步把打印密度换算回场景线性光:$I_{out} = 10^{-D}$。之后还有Paper Black开关:关闭时做黑点补偿(类似 ICC 相对比度量软校样),开启则保留纸张抬升的 D-max($10^{-2.3} \approx 0.005$),让最深处"黑得有纸味"。
在这条基础曲线之上,NegPy 还提供了一整套暗房工具:Preflash(预闪光)、Zone Density(分区密度)、Split Grade(分区分级)、Dodge & Burn(加光减光蒙版)、Contrast Mask(对比度蒙版,即暗房 unsharp mask)、Diffusion(扩散片模拟),以及对每个染料层(R/G/B)独立的crossover 修正——因为 CMY 色彩过滤只能"平移"某一层的曲线,只有形状修正才能修掉阴影与高光色偏不一致的问题。
内置纸张档案:从Ilford到Kodak的打印特性
🧪 纸张档案(Paper Profile)只改变 H&D 曲线的形状($D_{max}/D_{min}$、toe/shoulder 锐度与高度、中间调 gamma),对比度仍归 Grade 管。内置档案按处理模式分组:
| 纸张档案 | 类型 | D-max | 特点 |
|---|---|---|---|
| Neutral(默认) | 通用 | 2.3 | 与默认曲线逐位一致 |
| Ilford Multigrade FB Classic | 黑白 | 2.15 | 纤维纸,阴影更深、膝盖更锐 |
| Foma Fomatone MG Classic | 黑白 | 2.0 | 暖调氯化溴化,经典石印纸 |
| Kodak Polymax II RC | 黑白 | 2.13 | 依 G-26 数据表曲线拟合 |
| Kodak Portra Endura | RA4 | 2.65 | 依 E-4021 数据表拟合 |
| Kodak Ultra Endura | RA4 | 2.61 | 依 E-4020 数据表拟合 |
| Fujicolor Crystal Archive | RA4 | 2.35 | 鲜艳蓝绿,估算参数 |
档案定义:negpy/features/exposure/papers.py#L96-L239;Kodak 系列用 scripts/fit_paper_profile.py 对着数据表曲线拟合到 RMS ≤ 0.05 D 才接受。RA4 彩色纸还带染料耦合矩阵(如 Endura 的青染吸收部分绿光)与片基色 tint,模拟真实相纸的"串色"。
档案是模式感知的:彩色负片只出现 RA4 纸,黑白负片只出现黑白纸,幻灯片(E-6)只有 Neutral——存下来的不兼容值会自动回落到 Neutral,永远不会"泄漏"进渲染。
ISO-R分级教程:像暗房选纸一样调对比度
💡 NegPy 的对比度不用抽象的 0–5 数字,而是采用摄影标准ISO 纸级曝光范围(R 值):
- 滑杆范围R50(很硬)→ R180(很软),默认R115,其中 R110 ≈ 经典 2 级灰纸;
- 斜率换算:$k = 2.9 \times \text{负片密度范围} / (R/100)$,钳制在 [2.0, 10.0]——即"对比度 = 负片密度范围 ÷ 纸张曝光范围",和真实分级纸的物理定义完全一致;
- 旧版 0–5 纸级编辑自动迁移:$R = 150 - 20 \cdot G$,观感不变。
换算实现:negpy/features/exposure/logic.py#L861-L875(
grade_to_slope/slope_to_grade)
每个蒙版还能有自己的Local Grade(以 ISO-R 点偏移帧级分级),相当于"用一个更硬的滤镜烧天空"。
自动测光:Auto Density 与 Auto Grade 如何工作
这两个助手默认开启,且只读有纹理的区域(块中值 + 纹理投票,避免片基、天空和大白墙干扰测光):
| 助手 | 策略 | 目标密度 |
|---|---|---|
| Auto Density | 以 0.46 为假设锚点,按 20% 强度向实测值拉取,限幅 ±0.12 | 锚点打印至 0.75 D |
| Auto Grade | 按纹理密度范围(P10–P90)做"部分 ISO R 匹配",平的画面给一点提亮、硬的画面不硬推 | 正常负片目标 0.85 |
| Shadow Reach | 最暗纹理调子(P99)必须打出 ≥1.9 D,不足则抬高斜率(永不降低) | 1.9 D(直线段) |
| Highlight Hold | 最亮纹理调子(P2)若打过0.10 D,自动补一个高光减光 | 0.10 D |
| Shadow Hold | 对 Shadow Reach 尾巴做部分提亮(强度 0.40,上限 0.3) | 只提亮、不减光 |
实现:Shadow Reach negpy/features/exposure/logic.py#L1077-L1090、Highlight Hold negpy/features/exposure/logic.py#L1093-L1109、Auto Grade 因子 negpy/features/exposure/logic.py#L1032-L1039
此外还有Set Targets面板:这八个瞄准值(锚点打印密度、测光信任度、Shadow Reach 目标等)可以按自己的扫描仪和口味整体校准,属于"标定"而非"编辑",对已处理的帧同样生效。
负片处理流水线:从扫描到成图的9个阶段
📷 完整渲染顺序(各阶段串联,前级缓冲传给后级):
| # | 阶段 | 干什么 | 源码位置 |
|---|---|---|---|
| 0 | 修复烘焙 | IR 去尘/划痕检测,写回线性源(非阶段,先于几何) | negpy/features/retouch |
| 1 | Geometry | 旋转、畸变校正、tilt/swing、自动裁切 | negpy/features/geometry |
| 2 | Scan Normalization | 平面场校正、传感器串色解混、对数转换、百分位定界与拉伸 | negpy/features/exposure/normalization.py |
| 3 | The Print | H&D 曲线 + ISO-R 分级(本文主角) | negpy/features/exposure |
| 4 | CLAHE | CIELAB L* 上的局部对比度(8×8 瓦片) | negpy/features/lab |
| 5 | Lab Scanner Mode | 色度降噪、饱和度、肤色保护、锐化、辉光、红晕 | 同上 |
| 6 | Alt Processes | 石印 / 晒蓝 / Sabattier(仅黑白模式) | negpy/features/lith 等 |
| 7 | Toning | 六浴化学调色"银台账" + 分割调色 | negpy/features/toning |
| 8 | Finish | 边缘暗角、冲裁胶片边、装框、导出锐化 | negpy/features/finish |
色彩管理上,工作空间始终是线性 RGB(Adobe RGB 原色 + D65),Adobe RGB TRC 是引擎最后一步 OETF;软校样是一张 65³ 的 3D LUT 而非渲染阶段,导出时转换到目标色域并内嵌 ICC 档案——预览、缩略图与导出因此永远一致。
谁适合使用NegPy?
- 🎞️ 拥有负片/幻灯片扫描件(Plustek、Coolscan、SANE 扫描仪或相机 RAW)的胶片玩家;
- 想要"开箱即打印"的自然观感,又不想放弃暗房式手工控制(分级、加光减光、调色、石印);
- 在意无损编辑(源文件永不改动,编辑存于本地 SQLite,可选
.negpy旁挂文件)与预览-导出一致性(CPU/GPU 引擎逐位对齐)。
延伸阅读与源码导航
- 完整管线数学:docs/PIPELINE.md
- 面板与控件使用手册:docs/USER_GUIDE.md
- 串色解混档案(
.toml):docs/CROSSTALK.md 与 crosstalk/ - H&D 曲线与分级核心:negpy/features/exposure/logic.py
- 纸张档案数据:negpy/features/exposure/papers.py
- 数据表曲线拟合脚本:scripts/fit_paper_profile.py
【免费下载链接】NegPy
Tool for processing film negatives.
相关推荐
NegPy能做什么?这款开源胶片负片处理工具的完整介绍
NegPy能做什么?这款开源胶片负片处理工具的完整介绍 NegPy 是一款免费开源的胶片负片处理工具,专为负片扫描而设计。它不只是简单地把负片反转成正片,而是用
在 GitHub Codespaces 中云端构建 INAV 固件:从创建 Codespace 到下载 .hex 的完整指南
在 GitHub Codespaces 中云端构建 INAV 固件:从创建 Codespace 到下载 .hex 的完整指南 本文整理自 INAV 官方开发文档
ReelMimic多AI Agent审片流水线揭秘:为什么每支镜头都不自审自改
ReelMimic多AI Agent审片流水线揭秘:为什么每支镜头都不自审自改 ReelMimic 是一款本地运行的 AI 视频制作工具:丢给它一支喜欢的参考视
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考