利用铁路网络作为平板扫描仪
摘要
这篇文章描述了一个项目,利用安装在火车和渡轮上的线性扫描摄像头来创建宽全景图像,灵感来源于数字扫描后端技术,并于EMFcamp 2026上展示。
<p><a href="https://lobste.rs/s/n7i1jn/using_railway_network_as_flatbed_scanner">评论</a></p>
查看缓存全文
缓存时间: 2026/08/18 14:19
# 将铁路网络用作平板扫描仪
来源:https://philo.gay/linecam/
将铁路网络用作平板扫描仪
*2026年8月17日 — 4,600字*
过去几个月,我一直在尝试使用工业线性扫描相机从火车和渡轮上拍摄超宽幅照片。实现这一目标颇具挑战,但我认为最终成果不言而喻。
*拍摄于2026年2月旧金山至奥克兰渡轮上(56,894x2,048像素灰度图像);滚动可放大,点击拖动可移动查看更多细节*
更多图片可在图库(https://philo.gay/linecam/gallery.html)中浏览。
我已在EMFcamp 2026 (https://emfcamp.org/)介绍了这个项目,您可观看下方视频或继续阅读更详细的文字叙述:
[](https://media.ccc.de/v/emf2026-74-1-using-the-railway-network-as-a-flatbed-scanner)
## 这到底是什么原理?
[](https://philo.gay/linecam/blogpics_full/diagram-motion.jpg) 拍摄上述集装箱港口图像的完整过程示意图。
相机镜头指向移动车辆外部,持续捕捉单一垂直线条——类似图中所示的灰度条纹,但实际线条更细。随着相机移动,其捕捉的画面内容不断变化。若以足够快的速度从相机中采集这些线条并拼接,就能生成看似完整的图像。实际过程*稍显复杂*,且要获得良好效果颇具挑战,但这就是核心原理。
## 背景与技术沿革
上世纪90年代,数字相机传感器技术尚未达到中画幅和大画幅胶片的尺寸与有效分辨率,因此数字扫描后背(https://en.wikipedia.org/wiki/Digital_scan_back)应运而生。这类设备通过移动单线条像素(彩色版本为三条线)扫过画幅,无需庞大像素阵列即可获取高分辨率图像。经过数十年发展,图像传感器尺寸已大幅提升(如今甚至出现了覆盖4x5英寸大画幅的传感器( http://largesense.com/index.php/products/4x5-large-format-digital-back-ls45)),但对于大画幅设备而言,线性扫描方案的制造成本仍低于巨型传感器。
我曾多次考虑为大画幅相机制作自己的数字扫描后背,但始终未能实现——主要觉得制作与相机完美适配的装置过于困难。(购买成品*或许*是种选择,但90年代的产品在eBay上仍需数千美元,且需要重构同年代的计算环境才能使用。)去年末,我在观看Gigawipf的中画幅扫描相机制作视频(https://www.youtube.com/watch?v=KSvjJGbFCws)时突然想到:"如果整个相机移动而被摄体静止会怎样?"于是决定尝试实践。
[](httpsphilo.gay/linecam/blogpics_full/largeformat.jpg) 在佛蒙特州山顶往大画幅相机中装填胶片——我就是无法用常规方式进行摄影。(该次旅行拍摄的照片在此(https://tacobelllabs.net/@flamingspork/117028625866954702)。)
我发现了几个同类项目(Scannoramic项目(https://scannoramic.net/)、John Hikerbiker的实验(https://www.johnh.eu/photography/slit-scan-jan-2018.html)、Daniel Lawrence Lu的静态相机反转方案(https://news.ycombinator.com/item?id=45001125)以及Martin Liebscher极具创意的胶片作品(https://martinliebscher.de/martin-liebscher-destinations/)),但认为效果仍有提升空间。考虑运动速度并获得更清晰的图像应该不难,对吧?
## 扫描我的沙发
提出"大型扫描仪"概念的当晚,我便迫不及待开始实验。深夜不适合外出乘火车,于是我转而扫描自家沙发。
我把手机放在办公椅上,边缓慢推椅移动边录制视频。随后编写了一段极其粗糙的代码(为保护读者阅读体验,此处不公开)来提取每帧的最左列像素(即"狭缝"),并将它们组合成图像。
代码注释里引用了The Beths乐队《Future Me Hates Me》(https://www.youtube.com/watch?v=iVImwSb4EYU)的歌词,这竟成了某种自我应验的预言——后来在编写基于此代码的下一代相机后处理程序时,我不断咒骂自己当初的决定。
[](https://philo.gay/linecam/blogpics_full/out1.png) 勉强能看出是沙发,但图像严重变形,墙上的画作难以辨认。肯定能做得更好。
[](https://philo.gay/linecam/blogpics_full/out2.png) 我调整后处理方式并翻倍复制每列像素,减少了挤压感,但效果依然糟糕——因为推椅速度不够稳定。
从一开始我就知道需要某种方式测量速度,但天真地以为不必测量得*特别*精确,只需大致估算即可。然而这张图证明即使微小的速度变化也会产生影响。这让我首次意识到处理速度校正将多么棘手。
作为第二阶段实验,我乘坐了MBTA橙线。将旧手机用胶带固定在座位上采集加速度计数据,同时将当前手机紧贴车窗,确保将帧率提升至60fps。
加速度计数据实用性有限,对其积分求速度后效果更差。[](https://philo.gay/linecam/blogpics_full/wellington-acceleration.png)[](https://philo.gay/linecam/blogpics_full/wellington-velocity.png) 若我没记错,`y`轴对应列车行驶方向,但数据噪声过大,显示列车在末端似乎向后移动。
尽管如此,结果仍显有趣。但要获得清晰可辨的图像,显然需要采集更多扫描线条。[](https://philo.gay/linecam/blogpics_full/wellington1.jpg)
筹备EMFcamp期间,我注意到日程中还有Tim Jacobs(网络昵称mitxela(https://mitxela.com/))的演讲(https://media.ccc.de/v/emf2026-205-1-the-xelatype-a-journey-through-time-and-space)也涉及狭缝扫描相机,不禁担心我们做了完全相同的事情。(我的演讲结束后,他冲过来告诉我他也*曾*有过这种担忧。)他的演讲*开头*同样展示从视频中提取狭缝的方法,但最终通过遍历给定视频的所有狭缝位置,创作出酷炫的迷幻动画效果。
## 工业线性相机
为获得更高线条采集率,我最终选择了Basler ruL2048-19gm(https://www.altavision.com.br/Arquivos/Basler/Manual/Manual_Runner_GigE.pdf)——一款专为高速传送带设计的工业相机。其独特命名源于能以接近每秒19,000次的速率读取1x2048像素图像传感器。
[](https://philo.gay/linecam/blogpics_full/baslercam.jpg)[](https://philo.gay/linecam/blogpics_full/monosensor.jpg)
不过这些性能需付出代价:全新设备最低规格型号售价约700美元。幸运的是,我在eBay上以十分之一的价格找到了这台相机。
代价也体现在光线上:由于采集速度极快(最慢曝光时间为1/100秒),需要*大量*光线。我只能在白天拍摄,且几乎无法进入非明亮车站和隧道区域。
令我惊讶的是,之前接触过厂商软件的我无需支持合同或购买凭证即可从Basler官网下载SDK(https://www.baslerweb.com/en-us/downloads/software/1932603569/?downloadCategory.values.label.data=pylon)。最新版本仍支持这款2013年的相机,虽在意料之中但着实便利。
相机通过千兆以太网与计算机通信,只要网络接口配置了APIPA地址(169.254.0.0/16),软件就能自动发现设备。虽然可以为两端设置静态地址,但我一次只使用一台相机,故未费心修改。
出乎意料的是,SDK使用相对顺畅,除了抱怨其用"快门时间"而非"快门速度"的表述,以及对此相机"帧"概念的困惑外,我成功编写了采集像素缓冲区并写入磁盘的程序。
[](https://philo.gay/linecam/blogpics_full/12-05_12-44.jpg) 这是用自己编写的程序首次从相机获取的图像,我认为手持拍摄的效果相当不错。
## 装置与机械设计
为便于携带相机乘坐火车而无需三只手操作,我需要将其固定在三脚架上。最终设计了一个实用主义外壳,底部嵌入热熔螺母(https://www.mcmaster.com/94459A737/),由朋友Brooke(https://breq.dev/)3D打印完成。购买零件让我得以首次在McMaster-Carr下单,体验了一把真正的工程师感。
[](https://philo.gay/linecam/blogpics_full/case.png)[](https://philo.gay/linecam/blogpics_full/case2.png)
首次打印失败,因为完全忘记了"制造公差"这回事。
[](https://philo.gay/linecam/blogpics_full/case3.jpg) 糟糕,尺寸偏小了。
[](https://philo.gay/linecam/blogpics_full/diagram-setup.png) 现在想来,或许不该用蓝色美纹纸胶带粘贴传感器,但粘合效果相当牢固。顺时针方向的电路板依次为:
- 六轴加速度计/陀螺仪(https://www.adafruit.com/product/4692),可通过数学运算推算速度
- GPS模块(https://www.adafruit.com/product/4415),效果未达预期——波士顿地铁对GPS信号的屏蔽效果太好
- SAMD21微控制器(https://www.adafruit.com/product/4600),负责将数据传回笔记本电脑
前镜头是我为普通相机准备的维维塔28mm f/2.8镜头,通过宾得K卡口转C螺口的转接环安装在相机上。由于部分拍摄目标较高,该镜头的视角相当合适。
整套设备通过USB-C移动电源供电,并通过网线和USB线连接笔记本电脑,工作时宛如线缆丛林怪兽。
安装传感器后终于可以测试。[](https://philo.gay/linecam/blogpics_full/accel_dis.jpg)[](https://philo.gay/linecam/blogpics_full/accel_en.jpg) 两图均为在窗外前后挥动相机的拍摄成果,上方为原始图像,下方则应用了加速度计运动补偿。如图所示,使用加速度计后图像更接近正常比例,变形明显减少。(稍后在"后处理地狱"章节(https://philo.gay/linecam/#postprocessing-hell)将详细解释原理。)
## 波士顿实验
组装完成后,是时候带上它乘火车了。
[](https://philo.gay/linecam/blogpics_full/12-14_15-11_extract1.jpg) 从离家最近的MBTA橙线开始尝试,但如图所示效果欠佳。预览相机输出很麻烦,曝光只能靠猜,而我显然猜错了。编写的后处理代码效果不佳,图像存在轻微的拉伸和压缩变形。
[](https://philo.gay/linecam/blogpics_full/roxcross_clip.jpg)[](https://philo.gay/linecam/blogpics_full/roxcross_clip2.jpg) 在天气更好的日子再次尝试,曝光效果有所改善,不过焦点似乎略有偏差。与手机拍摄的试验不同,车站标识文字相当清晰,证明扫描线条数量充足。
[](https://philo.gay/linecam/blogpics_full/longfellow_extract1.jpg)[](https://philo.gay/linecam/blogpics_full/longfellow_extract2.jpg) 最满意的是这张从波士顿到剑桥的Longfellow Bridge(https://en.wikipedia.org/wiki/Longfellow_Bridge)图像。可在图库(https://philo.gay/linecam/gallery.html#4)中查看更高清版本。
## 图像采集(过于详细的记录)
[](https://philo.gay/linecam/blogpics_full/pylon-screenshot.png) 在波士顿拍摄初期图像时,使用相机厂商提供的Pylon工具预览。黑色水平区域是任意时刻可见的图像全部内容,且显示方向旋转了90°。调整曝光、释放相机控制权、在列车启动前重启自己的程序——这个过程极其繁琐,必须找到解决方案。
首次尝试使用OpenCV`highgui`(https://docs.opencv.org/4.13.0/d7/dfc/group__highgui.html)编写图形界面,但效果不佳。该库要求每帧后延迟1毫秒,这对低速相机尚可接受,但会导致我在每个显示帧(256行)中丢失整整4行数据(按常用快门速度计算需250微秒)。
最终选用Dear ImGUI(https://github.com/ocornut/imgui),能与现有的帧采集循环良好配合。在该库支持的约二十种后端中,我选择了GLFW("girl love for workgroups"——引用当时朋友的玩笑话)和OpenGL3,或许正是受那个玩笑影响,尽管我不太确定。
[](https://philo.gay/linecam/blogpics_full/capture1.png) 我在多伦多彻夜编写了大部分图形界面代码,当时旋转图像感觉像是计算机科学最艰难的问题。(我确定自己采用的实现方案仍有改进空间,但目前运行状况尚可。)遗憾的是,多伦多拍摄的图像效果一般,至少曝光是正确的。
[](https://philo.gay/linecam/blogpics_full/capture-chat.png) 在添加图像直方图功能时遇到了奇怪的bug。
获取加速度计数据实属不易。首个版本通过串口发送文本格式的读数,这对微控制器计算负担过重。(即使在性能相对较强的32位SAMD21微控制器上,浮点数转字符串再拼接也极其耗费资源。)我决定将转换工作移至计算能力更强的笔记本电脑进行,但这也带来了新问题。
[](https://philo.gay/linecam/blogpics_full/scan-parse.png) 令人抓狂的调试过程。
加速度计数据以原始浮点数发送,而GPS数据仍采用NMEA语句(https://en.wikipedia.org/wiki/NMEA_0183)格式。切换时需发送特定字节序列,并祈祷这些序列不会被误读。(虽然NMEA语句中不可能出现我的加速度计数据起始序列`0x11 0x11 0x11 0x11`,但加速度计数据中确实可能出现我的NMEA字符串起始序列`0x22 0x22 0x22 0x22`。)
还遇到因未在正确时机刷新串口导致整天拍摄数据作废的情况。幸运的是,当时我在波士顿Mattapan Line(https://en.wikipedia.org/wiki/Mattapan_Line)上采集,可以轻松重试。[](https://philo.gay/linecam/blogpics_full/mattapan_scrungled.jpeg) 图像中的"接缝"处丢失了约半秒的串口数据——对线扫描相机而言这已是永恒。
相似文章
将铁路网络用作平板扫描仪 [视频]
一场来自EMF 2026的演讲,关于使用工业线阵相机对着火车窗外拍摄,以创建极宽的全景照片,涵盖速度测量、快速线捕获以及拼接/显示巨大图像等技术挑战。
@marcinplaz: 我坐在办公桌前见证了 Midjourney 扫描仪的搭建;这是幕后花絮
Midjourney 扫描仪搭建过程的幕后花絮,该工具可能用于将图像扫描到 AI 艺术平台。
Launch HN: Transload (YC P26) – 通过监控摄像头自动测量货运物品尺寸
Transload利用现有货运站的安防摄像头自动测量零担货物(LTL)的尺寸,帮助承运商在不改变工作流程的前提下改善定价和挂车利用率。
Behind the scenes with the Midjourney scanner [video]
视频展示了Midjourney团队开发的全身超声波扫描仪原型,使用40个改装探头在水箱中同时扫描,旨在提供低成本、易获取的3D医学成像,虽不取代MRI但有望改善医疗可及性。
通过USB/IP将浏览器内Linux虚拟机与WebUSB桥接,复活旧扫描仪
介绍yes-we-scan.app,一款使用浏览器内Linux虚拟机(v86)和WebUSB的网络应用,通过浏览器中运行SANE,让用户无需原生驱动即可复活旧USB扫描仪。