把铁路网当成平板扫描仪:用工业线阵相机拍超宽照片
文章摘要
作者 Philo 用一台工业线阵扫描相机,从行驶的火车和渡轮窗口拍出极宽的照片,这篇 4,600 字的长文(2026 年 8 月 17 日)记录了整个折腾过程。开篇的样片是 2026 年 2 月在旧金山到奥克兰渡轮上拍的,56,894 × 2,048 像素灰度图。她在 EMFcamp 2026 做过同题演讲。
原理。 相机对着窗外,持续只捕捉一条竖直的线(比示意图里的还要细得多)。随着相机移动,它看到的内容不断变化;只要采线足够快再拼起来,就能得到一张看起来完整的图。「比这复杂一点,让结果好看相当棘手,但这就是主要思路。」
先例。 1990 年代数字传感器还赶不上中大画幅胶片的尺寸和有效分辨率,于是有了数字扫描后背——靠移动一条(彩色则三条)像素线扫过画面来获得高分辨率,而不需要一整块巨大的像素阵列。如今传感器已经很大(甚至有覆盖 4×5 英寸大画幅的),但这个思路对大画幅仍然更便宜。作者一直想给自己的大画幅相机做个扫描后背却始终没动手(买现成的:1990 年代的机器在 ebay 上仍要数千美元,还得复原同时代的计算环境)。去年底她看 Gigawipf 的中画幅扫描相机视频时忽然想到:「如果整台相机在动、被摄物不动呢?」她也找到了几个同类先例(Scannoramic 项目、John Hikerbiker 的实验、Daniel Lawrence Lu 把静止相机反过来用、Martin Liebscher 的胶片作品),但觉得结果还能改进——「把运动速度考虑进去、拿到更干净的结果,应该不难吧?」
第一次试验:扫沙发。 想到这个「大扫描仪」概念的当晚太晚了不便出门坐火车,她就把手机放在办公椅上边推边录视频,然后写了段极其潦草的代码(「为保护读者我选择不公开」)取每帧最左边一列(一条 slit)拼起来。结果「有点像我的沙发,但被压扁了,墙上的画完全看不出来」。她把每列复制一份让画面不那么压扁,但因为推椅子速度不匀,仍然一团糟。她一开始就知道需要测速度,但天真地希望不用测得太准、能糊过去;这张图说明即使很小的速度变化也会有影响,这是她第一次窥见「处理速度」会有多痛苦。下一步她坐 MBTA 橙线,把旧手机用胶带粘在座椅上采加速度计数据,新手机贴着车窗以 60 fps 录像。加速度计数据不太有用,积分成速度后更没用——「如果我没记错,y 是列车运动的轴,但数据噪声大到列车在末尾居然在倒着走。」结果看起来有意思,但要拿到清楚可读的图像还需要多得多的线。准备 EMFcamp 时她发现 Tim Jacobs(网名 mitxela)也有一场关于 slit scan 相机的演讲,一度担心撞题(对方演讲后跑来说他也担心过同一件事);mitxela 的起点相同,但最终是遍历一段视频里所有可能的 slit 位置,做出很酷很迷幻的动画。
工业线阵相机。 更多线数的来源是 Basler ruL2048-19gm,本是用来对准高速传送带的:这个古怪大小写的型号名来自它能把 1×2048 像素的传感器每秒读出接近 19,000 次。代价一是钱——厂商现售最低配的新机约 700 美元,她在 ebay 上以十分之一价格买到;二是光——因为采集太快(最慢曝光时间 1/100 秒),非常吃光,只能白天拍,除最亮的车站和隧道外都拍不了。让她意外的是 Basler 不需要支持合同或购买凭证就允许下载 SDK,而且最新版仍支持这台 2013 年的相机。相机通过千兆以太网通信,只要网卡配置为 APIPA 地址(169.254.0.0/16)软件就能自动发现它。除了对厂商用 shutter time 而不是 shutter speed、以及这台相机上「一帧」到底指什么略有抱怨,她「出乎意料地很少骂 SDK」,很快写出抓像素缓冲并写盘的程序。
机械与硬件搭建。 为了能带上火车而不需要三只手,她设计了一个相当实用主义的外壳、底部装热熔螺母以便上三脚架,由朋友 Brooke 3D 打印(第一版没成,因为她「完全忘了有种东西叫制造公差」);买零件让她终于有理由在 McMaster-Carr 下单,「感觉像个真正的工程师」。传感器板用蓝色美纹胶带贴着(「事后想想我大概该用别的东西粘,但它挺牢的」),顺时针分别是:六自由度加速度计/陀螺仪(配合数学计算得到速度)、GPS(最终不太好用,因为波士顿的列车太善于屏蔽 GPS 信号)、SAMD21 微控制器(把数据转发给笔记本)。镜头是她原本给普通相机用的 Vivitar 28mm f/2.8,通过 Pentax K 转 C 口的转接环装上;由于要拍的一些东西挺高,这个视角刚好合适。整套由 USB-C 充电宝供电,还有以太网线和 USB 线连到笔记本,工作时是一团「线材意面怪物」。加了传感器后的对比图显示:同一次「把相机伸出窗外来回挥」的采集,原始图和考虑加速度计运动后的图相差极大,后者接近正常、不再被拉伸。
波士顿的尝试。 先上 MBTA 橙线(离家最近),结果不好——预览相机输出很麻烦,只能猜曝光,而且猜错了,后处理代码也不太行,画面被诡异地拉伸和压缩。天气好的一天再去,曝光运气好些,但对焦大概搞砸了;不过与手机版本不同,站牌上的文字已经清晰可读,说明线数确实够了。她对其中一张从波士顿到剑桥的 Longfellow Bridge 特别满意。
采集(细节过多的一节)。 早期在波士顿拍时她用厂商的 Pylon 工具预览,能看到的只有一条黑色横带、而且相对她想看的方向旋转了 90°;在里面调好曝光、释放相机占用、再在列车开动前把自己的代码启回来,是件真正的苦差事。她第一版 GUI 用 OpenCV 的 highgui,不合用:它要求每帧后有 1 毫秒延迟,对慢相机没问题,但对她意味着每显示一帧(256 线)就丢掉整整 4 条线(在她常用的快门速度下每条 250 微秒)。改用 Dear ImGUI 就与已有的帧采集循环配合良好;在该库支持的约二十几个后端里她选了 GLFW(引用当时朋友的消息,戏称其为「girl love for workgroups」)和 OpenGL3,「大概就是因为那个 girl love 的梗」。GUI 大部分是在多伦多一个不眠之夜写的,当时「把图像旋转过来感觉像是计算机科学里最难的问题」。加速度计数据也很折腾:第一版把读数以文本经串口发送,结果在微控制器上计算开销极大(把浮点数转成字符串再拼字符串非常贵,即使在「有整整三十二个比特」的 SAMD21 上也如此);她把转换挪到笔记本上,却带来新问题——加速度数据以原始浮点数发送,而 GPS 数据仍是 NMEA 语句,两者切换要靠发送固定字节序列然后祈祷别被误判(NMEA 语句里不该出现 0x11 0x11 0x11 0x11,也就是她的加速度数据起始序列;但加速度数据里出现 0x22 0x22 0x22 0x22,也就是 NMEA 起始序列,并非完全不可能)。她还遇到过没在正确时机 flush 串口而毁掉一整天素材的情况——图中那道「缝」就是丢失了约半秒串口数据的地方,「在线阵相机的时间尺度上这是一个永恒」,软件一直在等一个永远不会到来的加速度采样,因为串口缓冲已满。
「See It, Say It, Sorted」(安全与围观)。 组装好的相机看起来是一团可疑的乱麻,用它的「女巫」看起来也不比它正常。尽管波士顿历史上有对无害电子项目反应过度的警方记录,她在 MBTA 上最不担心被抓:这里的人习惯各管各事,从没有人报过警;警察也不常坐车,更喜欢在车站骚扰人。在别的城市她只在有朋友同行时才带相机出门(有时还听调度电台)。「到目前为止我只被看见(seen),还没被说(said)或被处理(sorted)。」在蒙特利尔的 Gare Centrale 她被保安拦下,被告知不许用三脚架,并被以「franglais」问是在录像还是在拍照——「与其用我不会的语言回答这个哲学问题,我就说了几声 désolé 并收起三脚架,看起来这就够了。」
后处理地狱。 采集图像和加速度数据反而是简单的部分。相机每秒约采 4,000 线,每次拍摄的线都比需要的多,必须挑出真正要用的。取线太少会出问题;线之间跳得太快会显得人工、不对劲(在奥克兰渡轮早期版本做的专辑封面里,水线处能明显看出来)。她用加速度计测的速度来决定取哪些线,但这带来几个问题:第一,加速度计并不测速度,它测加速度,积分得到的速度是相对于某个初始值的;她通常可以假设起点在车站因此初速为零,但无法确定,如果不为零就只能猜到「闻起来对」的值。第二,加速度计的采样率有限,相机取线大约比它快 4 倍,因此每几条线得共享一个速度值;而且由于她的微控制器代码不够快,采样也不够规整,会在最终图像里造成不规则;加速度采样的多少还会改变积分的准确度,制造更多问题。GPS 基本没用:大多数列车上收不到信号,收到时也只有每秒 10 次,而这覆盖了相机整整 400 条线;如果它更稳定,本可以用卡尔曼滤波来校正积分误差,「但那是等我有更好的 GPS 数据再说的问题」。第三,即使速度测得完美,还有视差问题——离相机近的东西看起来移动更快,这与光学对焦无关(她通常把焦点设在无穷远)。应对办法是调整「每个像素代表多少距离」:值越小越强调近处,越大则背景越清晰。文中做了个滑块交互演示,每张图都是 10,000 × 2,048 像素、单位是任意的(「我可以换成真实的米每像素,但看不出有什么意义」)。相机和软件不知道她想「聚焦」什么,所以这是她为每一段画面手工做的艺术决定,然后把各段拼起来;她测试不同的每像素距离和每段起始速度,再在 GNU IMP 里拼成最终图。拼好的图往往超过 JPEG 的 65,535 × 65,535 上限,于是用老牌的 TIFF 格式(PNG 规范理论上也允许类似大小,但手边软件更吃大 TIFF)。把加速度数据应用到每一行的程序叫 grindstone(磨石),因为它把数 GB 的原始采集「磨」成可用的小图;第一版基于她早期那段很糟的 slit scan 代码,极慢,处理几分钟的采集要几小时,而且常常跑几小时后因为图太大存不成 JPEG 而失败,调试也极痛苦。她「把朋友 Maddie 狙击进来」用符合 NumPy 惯用法的方式重写了 grindstone,让其中的数学运算更清晰(Maddie 坚称所有运算原本就在,她的改动更像是「把它变身成魔法少女」);后来 Maddie 又把它拆成一条「也许略微过度工程」的多阶段流水线,便于试验、替换不同的运算和输出策略。
色彩地狱。 4 月她和朋友 Ari 在树叶初生时坐 Mattapan 线,照片因采集软件的 bug 没成,但让他们想到彩色线阵照片会很好看,秋天尤其。深夜刷 ebay 时她捡到同代彩色线阵相机的好价——Basler ruL2098-10gc,3×2098 像素、每秒约 10,000 线;拆掉工厂产线上用的外壳、换过镜头座就机械就绪了。她给三台相机贴了红绿蓝条纹以便不摘镜头、不去眯着看铭牌上的小字就能分辨。采集软件侧不算太难,但要修一堆关于每条线大小的假设、重做 GUI 的旋转。得益于 Maddie 那次高度模块化的重写,加彩色支持也不太难。随后新问题冒出来:最明显的是树叶远比应有的亮。原因是彩色相机的三个通道都对红外敏感(如果只有红通道敏感,叶子会偏红;三通道红外叠加强烈的可见绿,就变成偏绿的白);单色相机同样对红外敏感,但只有一个通道、可见光完全压过它所以无所谓。她承认在合适光线下这效果挺好看——在波士顿以北 Manchester-by-the-Sea 拍的一张「既是灰度又同时有色彩」。她用只透过 400–700 nm 的紫外/红外截止滤镜解决了它,接近人眼可见光谱,一切看起来就对了,后期只需极小调色。她还试了只透过 720 nm 以上的滤镜(配红外敏感胶片曾有很有趣的结果),打算以后多拍。另一个问题是某些物体出现奇怪的红绿蓝边缘,尤其是离相机更远或移动更快的主体。这源于传感器本身的工作方式:红绿蓝是三条各自独立的竖线(而不是拜耳滤镜),因此无法在同一时刻看到完全相同的东西;当只有一条线看到某物时就出现色边,明亮主体尤其明显;边缘是斜的而非完全竖直,因为相机本身不完全垂直(她尽量摆正,但在行驶的列车上能做的有限)。厂商在手册里给了可用镜头光学放大倍率和精确速度来抵消它的公式,但她没有主体的(相对)速度估计。她的做法是针对某个主体,把红蓝通道平移去对齐绿通道;因为三条线等距,只需在相反方向平移相同量而不必逐通道测量。理论上可以靠通道间亮度变化的相关性自动决定平移量,目前还是手工。示例中帆船桅杆上的通道分离通过红通道右移 10 像素、蓝通道左移 10 像素修正;背景仍有色边,因为它远得多、角速度更快,可以为它单独校正但那样帆船会难看得多。
展示。 显示和分享这些照片一路都是麻烦:电脑上多数软件都受不了这个尺寸,她找到最可靠的查看工具是 GNU IMP(「感觉有点大炮打蚊子」);发给朋友的聊天软件也受不了超宽图,有时会压成一小团垃圾。她担心浏览器里也一样痛苦,好在 OpenSeadragon 项目已经把重活干完了,提供了缩放浏览大图的简便方式。她用 vips 工具把巨大的 TIFF 切成小 JPEG 瓦片来提供,并自己写了点 JavaScript 支持深链到图库(主要是为了让这篇博文好写)。「Web 开发不是我擅长的事,所以为它最后长得这么丑道歉。」
后续计划。 最大一项是让相机不再依赖笔记本来采集,这会让它看起来不那么可疑、也更方便带出门,为此要修掉一些困扰她的加速度数据采集和采集 UI 问题。后处理工具也要改进:想做成读一份「行号」表格再拼装的形式;如果有雄心,还想做个能标出段落并以不同每像素距离预览的 GUI;也想真的用上 GPS 并实现卡尔曼滤波(「不过我估计会一直往后拖」)。此外想拍更多奇怪的红外照片,也许做 ærochrome 式的换色。还想标定相机增益设置与 ISO 的对应关系,这样就能只带测光表去踩点(此前试过,但室外光照条件变化太快拿不到好结果)。采集端代码和后处理器 grindstone 都已开源。文末她感谢了 Meadow、Brooke、Ari、nyanotech、cat、Maddie、kim 在坐车/坐船、机械设计、3D 打印、代码、演讲准备和校对上的帮助。
HN 评论精华
这条帖子 450 分、71 条评论。讨论主线不是质疑而是「共鸣与考古」:大量人拿出自己或别人做过的同类项目(从 1990 年代把平板扫描仪装在电机上,到 2008 年 Ward Cunningham 的午后 hack,到卫星成像和终点线摄影),并指出线阵扫描其实是铁路检测、工业质检和照相判定的成熟工艺。也有少数技术性异议和改进建议。
- mhb 指出 17 天前有过一个相关帖(85 分、34 评论)。toomuchtodo 澄清是同一个人:这篇是博客文章,另一个帖是她的 CCC 演讲。
- dorfsmay 回忆有人把平板扫描仪装在电动马达上、在数码相机还不存在的年代做出数字照片,并贴了后院的成图,当年是 Slashdot 上最火的帖子之一。4gotunameagain 找出了链接,ink_13 补充作者是 Matthias Wandel——「当年他给 BlackBerry 写软件,现在是半退休的木工 YouTuber」。
- grumbelbart2 一句话点出这正是工业实践:铁路运营方就是这么检查轨道的——装一台朝下的线阵相机,得到一张「无限长」的轨道图像再检查异常。adamjb 贴了检测车的图片和视频。13hours 说这也是(大多数)卫星拍照的方式,russdill 补充说「把这件事做到极致就是从太空做」。mhb 补了另一条产业线索:Lynx 的终点线照相机(FinishLynx)是同一个思路。
- crote 给出线阵相机的产业背景:它们在工业应用里(曾经?)非常常见,是拍摄高速传送带上物体的最佳方式,不必担心长快门造成的模糊,还能达到惊人的帧率;缺点是高度专用(换言之昂贵)并且需要知道带速才能重建正确图像,他猜现代高帧率视频相机可能已经吃掉了一部分这个细分市场。zipy094(zipy124)反驳说线阵相机仍然极其常见,关键在于它逐行给你信息因此延迟极低,价格其实不算贵、取速度数据也不难;他用过实时流式 10k FPS 以上的现代高速相机,「目前根本比不了,主要是接口问题」,虽然有 DMA/采集卡的替代方案但还没占领市场。crote 还接了另一条有趣的历史考古:mofosyne 提到铁路曾试过在列车上贴线性条码并用类似方法读取,crote 说那是 KarTrak——最早的大规模商用条码应用之一,一度 95% 的铁路车辆装有它,「本来可能成功,但早了几十年,加上少数几个小而关键的实现缺陷,让它在十年后就被放弃」。
- msisk6 讲了个很有味道的往事:2008 年他和 Ward Cunningham 在波特兰一家初创公司做过类似的事。办公室在 Willamette 河东侧铁路旁的四五层,正上方有大量列车(包括 Amtrak)经过;他带来早期的外置 iSight 相机(当年是插在显示器顶上、用 FireWire 连 Mac 的设备),把桌子推到窗边、相机朝下对着轨道,Ward 现场写了个 slit scan。「列车速度会影响图像的水平压缩,我们可以调软件里单位时间的取线数来拉伸或压缩图像尺寸,当然那会影响曝光,我记得相机的自动调节给我们造成了麻烦。」那只是一个下午的 hack,两人当时都没太当回事,所以什么都没留下来。
- jonty 分享了自己多年前做的小玩具 slitscan.space,说自己常在火车上用:按住手机屏幕切换前后摄像头(电脑上按 c),点屏幕保存图像(或按 s)。有人玩得很开心,Aachen 报告只看到空白页,redsparrow 解释需要给它摄像头权限。
- decae 贴出自己用普通相机手工拼帧做的动画(每条「线」约 15 像素宽),说这个效果很有趣,会强迫注意力集中到主体上、把背景化成抽象图案,「我的思路过程和作者完全一样,想法能这样独立产生真有意思」;他还拍了东京天际线的日落延时并做同样处理(每条线 4 像素宽、原动画是 8K),再做运动跟踪让时间从左到右穿过画面。srean 说「东京进入黑夜」那张要想一会儿才明白,「非常美也非常聪明」。
- dllu(Daniel Lawrence Lu,正是原文引用的先例之一)现身两次,贴了自己 Caltrain 拍的房子,并说自己的长列车扫描装置又有改进:便携电池供电、带显示屏的外壳,以及通过手工标注做细粒度畸变校正,还给了一张最近的 Caltrain 照片(已上传到 Wikimedia Commons)。
- strohwueste 计划在德国做同样的事,本以为智能手机相机就够了,结果发现拿不到 camera2 API 做那种高速录制;他拍了一小时的 240 Hz 4K 竖屏视频(在伍珀塔尔的悬挂式单轨 Schwebebahn 上),现在在等一个好的高斯泼溅工具来在 Blender 里重建「列车行驶」。他的技术直觉是:横向运动和视差应该让推断距离和 3D 扫描容易得多,因为只要不过弯,像素就只沿一个方向移动。namibj 回应愿意深聊,强烈建议下次录制时同时录 IMU、理想情况还录带载波相位的 GNSS 原始观测量,并说自己有个能暴露成 USB 串口的记录器。strohwueste 说目标是拍汉堡到慕尼黑的 ICE(8 小时最长线路),但 300 km/h 下手机的 240 fps 不够、还是需要线阵相机,而且「窗口(字面意义上)正在关闭」,因为新 ICE 车厢内装了网格,隔着拍不了;另外 8 小时 4K 240/480 Hz 视频的数据量「有点吓人」。
- 少数批评与建议:PunchyHamster 直接反驳作者「结果不言自明」这句话——「不言自明是指跟普通相机相比并不太好吧?基于加速度计的校正能做的有限。普通相机给你的是 2D 区域快照而不是 1D,所以事后可以做任意运动校正;线阵相机你只会得到像开篇那张图那样上下很晃的伪影。」tvbusy 提了个有建设性的方案:同时用一台普通相机辅助拼图会不会比测加速度更简单?辅助相机不需要高分辨率,只要够对齐就行。andrewla 提了另一个方向:用行驶列车的视频做「视频立体图」,让一只眼睛在时间/距离上滞后于另一只,从而制造超长基线立体图,看桥梁经过时的 3D 效果很有趣,长直线段的大基线甚至能看到云的 3D 结构。Tepix 问有没有人对其他有轮子的载具做过同样的事,猜测那会变成 NeRF 和高斯泼溅。kmoser 说几年前从时速 150 英里的新干线车窗拍照,发现前景一切都明显向左倾斜,「这大概是我能最接近体验被吸进黑洞的样子了」;mkl 纠正说那听起来更像卷帘快门效应。cscheid 说这是他和 Bill Cheswick 近 15 年前用 SFO 飞 EWR 航班素材做的东西的「好得多的版本」。waltbosz 说这些晃动的图片让他回到小时候用手持扫描仪的体验——不可能在沿 Y 方向滑动的同时保持 X 轴手位不变,而且他记得那台扫描仪只能输出 1 bit 抖动黑白图(80 年代末 90 年代初的技术)。awwaiid 和 otherayden 都表达了对这类「用 X 当 Y」文章的喜爱,后者顺手宣传了自己做的只展示这类非 AI 帖子的站点。hn9zmdcaou 一句话总结了这篇文章为什么好:「诚实才是它出色的地方。」