[开源] 写了个相机 RAW 照片 GPS 轨迹对齐、智能插值与离线中文地名归档工具 photools
各位 V 友好。
平时喜欢带着相机到处跑,同时也是个写 Go 的程序员。每次外拍或者旅行回来,把几千张 RAW 照片导进电脑整理时,总会被照片的地理信息折磨:
- 相机时钟偏差:相机没内置 GPS ,用手机或佳明手表录了 GPX 轨迹,但相机时间和 GPS 总会差个几秒或几分钟,手动对齐繁琐,跨时区更是灾难;
- 室内/盲区断点:进了室内、隧道或者短暂停留时,手机没打上点,导致同一机位拍的照片一部分有坐标、一部分完全空白;
- 地名逆地理体验糟糕:Lightroom 之类的工具要么依赖联网,要么反查出来的中文地名不规范,更别提自动打上「某某风景名胜区 / 5A 景区」的 POI 了;
- 传统脚本慢如蜗牛:以前自己写 Python 调 ExifTool 批处理,每张照片都 fork/exec 一次子进程,上万张 RAW 照片能让风扇狂转半小时;
- 双格式同步容易漏:RAW + JPG 同拍或者带调色 XMP 时,元数据经常不同步。
折腾了一段时间,自己用 Go 撸了一套专门解决照片导入电脑后“第一公里”的元数据处理工具:photools。目前已经在 GitHub 开源。
- GitHub 地址: https://github.com/vincentchyu/photools
- 支持平台:macOS (原生 SwiftUI 客户端 / CLI / TUI) & Linux
做了哪些事情?
整个处理链路设计成了分阶段屏障流水线( Stage Barriers Pipeline ):
[待处理照片 RAW/JPG] ──▶ 1. GPX 轨迹匹配 ──▶ 2. GPS 智能插值 ──▶ 3. 离线逆地理 ──▶ 4. 拍摄日期归档 ──▶ [归档库/YYYY/MMDD/]
1. GPX 轨迹精准匹配与秒级偏差补偿
- 支持
-geosync时间偏移补偿(比如相机慢了 5 秒,直接设+00:00:05自动校准); - 采用主文件优先模型( Primary Asset Model ):以 RAW 为主决策源,写入坐标并二次校验,然后无污染同步到伴随的 JPG 和 XMP 。
2. 室内与断点自愈( GPS 智能时间插值)
很多时候在景区室内或峡谷拍的照片没命中 GPX 轨迹:
- 球面大圆时间加权插值:利用前一个有效机位和后一个有效机位,按拍摄时间在球面上插值推算;
- 同机位近邻继承:单侧锚点(刚进室内)直接继承最邻近机位,推算完动态合入索引,后面的照片就能自愈继承。
3. 纯离线 3D KD-Tree 高精逆地理(全国 90 万+ POI )
- 不调任何高德、腾讯或 Google 在线 API ;
- 纯离线加载全国 90 万+ 行政区划与风景名胜 POI 数据库;
- 毫秒级将 国家、省份、城市、区县、景区 POI 规范中文名写入 IPTC/XMP ,在 Lightroom 或系统相册里直接看中文地名。
4. 真实拍摄日期原子归档
- 读取 EXIF 真实拍摄时间,重命名为
YYYY-MM-DD-basename并安全移动到Processed/YYYY/MMDD/; - 支持软降级容错(
--allow-no-gps),没有 GPS 的照片也会安全归档,并自动生成一份 Markdown 排查清单(Logs/inbox_pending_report_latest.md)。
一些工程与性能实现
为了让批量处理几十万张 RAW 时不卡顿,做了一些底层优化:
1. ExifTool Stay-Open 守护进程池(速度提升 ~20 倍)
传统脚本慢是因为频繁启动 Perl 进程(单次 30~50ms )。photools 实现了基于管道通信的 StayOpenPool 常驻守护池(exiftool -stay_open True -@ -),单次读取开销压到了 1~2ms,并且支持子进程崩溃自愈。
2. 3D KD-Tree 空间索引 + O(log K) 时间分桶
- 空间:把经纬度投影为三维笛卡尔坐标 $(x, y, z)$ 建平衡二叉树,最近邻查询微秒级;
- 时间:插值阶段在内存中按天分桶维护有序切片,通过二分查找在 ~200ns 内定位前后邻近机位,批次首轮统一提取坐标,避免循环反复读 I/O 。
3. Go ➔ SwiftUI 进程内 C-Shared FFI 直通
macOS 客户端用原生 SwiftUI 写的,没有在本地开 HTTP 服务或搞 RPC ,而是把 Go 核心编译成了 libphotools.dylib 动态库,SwiftUI 通过 C-Shared FFI 在进程内直接调用,延迟在 0.1ms 左右。
界面展示
1. 工作区引导与离线 3D KD-Tree 反查

2. 多阶段流水线执行过程全景

3. 执行审计看板与待处理诊断清单

4. 终端 TUI 工作台(基于 Bubble Tea )
习惯在终端或 Linux/NAS 跑的同学,也可以直接敲 ./photools tui 启动交互式终端界面:
[1/2/3/4]快捷键开关插件;[O]调出插件设置;[S]全局设置(支持[Tab]路径补全);[Enter]预检与执行。
写在最后
项目完全开源,没有商业化诉求,主要是为了解决自己和身边摄影朋友的实际整理痛点。
如果你也是相机常客、对照片元数据/GPS 轨迹有强迫症,欢迎试用、提 Issue 或 PR !
- 项目 Repo: https://github.com/vincentchyu/photools
- 依赖:需要系统安装
exiftool(brew install exiftool)