Het spoorwegnetwerk gebruiken als een flatbedscanner

Wat zie ik hier eigenlijk?

Het proces van het vastleggen van een beeld (zoals een foto van een containerhaven) werkt als volgt: de camera is gericht vanuit een rijdend voertuig en legt constant een enkele verticale lijn vast. Dit lijkt op de grijstinten in een diagram, maar dan veel dunner. Terwijl de camera beweegt, verandert het beeld dat hij ziet. Als ik deze lijnen snel genoeg vastleg en aan elkaar plak (stitching), kan ik een compleet beeld produceren. De praktijk is iets ingewikkelder en het was lastig om de resultaten kwalitatief goed te krijgen, maar dat is het basisidee.

Achtergrond en bestaande technieken

In de jaren 90 was de technologie van digitale camerasensoren nog niet opgewassen tegen de grootte en effectieve resolutie van medium- en grootformaatfilm. Daarom werden digitale 'scanning backs' ontwikkeld. Deze leggen een hoge-resolutie afbeelding vast zonder een gigantisch raster van pixels nodig te hebben; in plaats daarvan beweegt een enkele lijn pixels (of drie lijnen voor kleur) over het frame. Hoewel beeldsensoren inmiddels erg groot zijn geworden, is deze benadering voor grote formaten nog steeds goedkoper dan het bouwen van een gigantische sensor.

Ik wilde al een tijd mijn eigen digitale scanning back bouwen voor mijn grootformaatcamera, maar de montage leek me te ontmoedigend. Recent zag ik een video over een medium-formaat scanning camera van Gigawipf en vroeg me af: "wat als de hele camera beweegt en het onderwerp stilstaat?".

Ik vond enkele eerdere projecten in dezelfde richting (zoals het Scannoramic-project, experimenten van John Hikerbiker, de omkering van de stationaire camera van Daniel Lawrence Lu en de filmopnames van Martin Liebscher), maar ik dacht dat de resultaten verbeterd konden worden. Ik nam aan dat het meenemen van de bewegingssnelheid voor een schoner resultaat niet zo moeilijk zou zijn.

Mijn bank scannen

Op de avond dat ik dit concept bedacht, wilde ik het direct proberen. Omdat het te laat was voor de trein, scande ik mijn bank. Ik zette mijn telefoon op mijn bureaustoel en duwde deze langzaam vooruit terwijl hij een video opnam. Vervolgens schreef ik wat provisorische code om de meest linkse kolom (een "slit") van elk frame te pakken en deze samen te voegen tot een beeld.

Het resultaat leek vaag op mijn bank, maar het beeld was erg ingedrukt en de kunst aan de muur was onleesbaar. Door elke kolom te verdubbelen in de nabewerking leek het minder ingedrukt, maar het bleef een puinhoop omdat ik de stoel niet met een constante snelheid voortduwde. Dit was mijn eerste inzicht in hoe problematisch het omgaan met snelheid zou worden.

Voor mijn volgende poging nam ik de MBTA Orange Line. Ik plakte mijn oude telefoon aan de zitting om de versnellingsmeter te gebruiken en hield mijn huidige telefoon tegen het raam, met de framerate op 60 fps. De data van de versnellingsmeter bleken echter niet erg nuttig, zeker niet na het integreren om de snelheid te bepalen; de data was zo ruisachtig dat de trein aan het einde schijnbaar achteruit bewoog.

Industriële lineaire camera

Om meer lijnen per seconde te kunnen vastleggen, ben ik overgestapt op de Basler ruL2048-19gm, een camera die ontworpen is voor snelle transportbanden. De naam komt voort uit het vermogen om de 1x2048 pixel beeldsensor bijna 19.000 keer per seconde uit te lezen.

Deze specificaties hebben een prijs: nieuw kosten de basismodellen rond de 700 dollar. Gelukkig vond ik er een op eBay voor een tiende van dat bedrag. Ook is er een prijs in licht: omdat de camera zo snel vastlegt (de langzaamste belichtingstijd is 1/100s), is er veel licht nodig. Ik kan alleen overdag fotograferen; donkere stations en tunnels zijn uitgesloten.

De camera communiceert met de computer via een gigabit ethernet-verbinding. De software vindt de camera automatisch, zolang de interface is ingesteld op APIPA-adressen (169.254.0.0/16). Met de SDK van de fabrikant heb ik een programma geschreven dat buffers met pixels pakt en naar de schijf schrijft.

De opstelling en het mechanische ontwerp

Om de camera in de trein te kunnen gebruiken zonder drie handen nodig te hebben, ontwierp ik een behuizing voor montage op een statief, die door mijn vriend Brooke is 3D-geprint.

Rondom de behuizing zitten de volgende onderdelen:

  • 6-assige versnellingsmeter/gyroscoop: wordt gebruikt om via berekeningen de snelheid te bepalen.
  • GPS: dit werkte minder goed dan gehoopt, omdat de treinen in Boston GPS-signalen te goed blokkeren.
  • SAMD21 microcontroller: stuurt de data terug naar de laptop.

Als lens gebruik ik een Vivitar 28mm f/2.8 met een adapter van Pentax K naar de C-mount schroefdraad van de camera. Het hele systeem wordt gevoed door een USB-C batterijbank, met ethernet- en USB-kabels naar mijn laptop.

Door de bewegingen van de versnellingsmeter mee te nemen in de nabewerking, ziet het beeld er veel normaler uit en minder uitgerekt dan bij een ruwe opname.

Pogingen in Boston

Met de volledige assemblage begon ik op de MBTA Orange Line. De eerste resultaten waren matig; het was lastig om het beeld live te bekijken, waardoor ik de belichting verkeerd inschatte. De nabewerkingscode werkte ook nog niet optimaal, waardoor beelden vreemd uitgerekt of samengedrukt waren.

Bij een tweede poging op een dag met beter weer was de belichting beter, hoewel de focus mogelijk niet perfect was. De tekst op stationsborden was echter leesbaar, wat betekende dat ik voldoende lijnen vastlegde. Een opname van de Longfellow Bridge tussen Boston en Cambridge was een van de hoogtepunten.

Het vastleggen van beelden (in veel te veel detail)

Voor de preview gebruikte ik aanvankelijk de tool Pylon van de fabrikant, maar dit was onhandig omdat het beeld 90 graden gedraaid was en ik slechts een klein deel tegelijk zag.

Ik probeerde eerst een eigen GUI te bouwen met OpenCV highgui, maar dit introduceerde een vertraging van 1 ms per frame. Bij mijn belichtingssnelheden zou dit betekenen dat ik elke display-frame vier lijnen zou missen. Ik ben daarom overgestapt op Dear ImGUI met GLFW en OpenGL3, wat veel beter samenwerkte met de acquisitie-loop.

Het verkrijgen van de versnellingsmeter-data was problematisch. De eerste versie stuurde data als tekst via serieel, wat te zwaar was voor de SAMD21 microcontroller (het omzetten van floating-point getallen naar strings is kostbaar). Ik verplaatste de conversies naar de laptop. Dit bracht nieuwe problemen met zich mee, zoals het onderscheiden van versnellingsmeter-data en NMEA-zinnen van de GPS.

Ook возникen er problemen met het niet tijdig legen van de seriële poort, waardoor er soms gaten in de data vielen. In een beeld uit zich dit als een "naad", waar de software wachtte op een sample die nooit kwam omdat de buffer vol was.

"See It, Say It, Sorted"

De camera ziet eruit als een verdacht geheel van hardware en tape. Ondanks de geschiedenis van overreacties van de politie op elektronische projecten in Boston, maakte ik me weinig zorgen op de MBTA; mensen laten elkaar daar meestal met rust.

In Montréal was ik echter in Gare Centrale gestopt door de beveiliging. Ze informeerden me dat statieven niet waren toegestaan en vroegen in een mengeling van Frans en Engels of ik aan het opnemen of fotograferen was. Ik antwoordde simpelweg een paar keer "désolé" en berging het statief.

Postprocessing-hel

Het vastleggen van de data was het makkelijke deel; de nabewerking om de beelden echt goed te krijgen was de echte uitdaging. De camera legt ongeveer 4.000 lijnen per seconde vast, wat meer is dan nodig.

Om te bepalen welke lijnen gebruikt moeten worden, gebruik ik de snelheid van de versnellingsmeter, maar dit brengt complicaties mee:

  1. Versnelling vs. Snelheid: Een versnellingsmeter meet versnelling. Door te integreren krijg ik snelheid, maar dit is relatief aan een beginwaarde. Ik neem meestal aan dat de start-snelheid bij een station nul is, maar als dat niet zo is, moet ik gissen.
  2. Sample-rate: De versnellingsmeter is trager dan de camera. Meerdere camerarijen moeten dus één snelheidsmeting delen, wat inconsistenties kan veroorzaken.
  3. GPS-beperkingen: De GPS leest slechts 10 keer per seconde, wat 400 camerarijen beslaat. Dit is te traag voor directe correctie, tenzij ik een Kálmán-filter zou implementeren.

Daarnaast is er het probleem van parallax: objecten die dichterbij de camera staan, lijken sneller te bewegen dan objecten in de verte. Dit kan worden opgelost door aan te passen hoeveel afstand elke pixel vertegenwoordigt. Omdat de software niet weet waar ik op wil "focussen", maak ik deze artistieke keuze handmatig per segment van het beeld en voeg ik deze segmenten samen in GNU IMP. De resulterende bestanden zijn vaak te groot voor JPEG (max. 65.535x65.535 pixels), waardoor ik het TIFF-formaat gebruik.

Het programma dat deze data verwerkt heet grindstone. De eerste versie was extreem traag. Mijn vriend Maddie heeft grindstone vervolgens herschreven in idiomatisch NumPy, waardoor de wiskundige operaties helderder werden en de pipeline efficiënter.

Kleur-hel

In april ben ik overgestapt op een kleurencamera, de Basler ruL2098-10gc (3x2098 pixels, circa 10.000 lijnen per seconde).

Dit bracht nieuwe problemen met zich mee:

  • Infraroodgevoeligheid: De camera is gevoelig voor infraroodlicht op alle drie de kanalen. Hierdoor werden bladeren in de natuur bijna witgroen in plaats van groen. Dit heb ik opgelost met een UV- en IR-cut filter (400-700 nm).
  • Kleurfranjes: Er ontstonden rode, groene en blauwe randen bij objecten, vooral in de verte. Dit komt doordat de R-, G- en B-sensoren drie aparte verticale lijnen zijn in plaats van een Bayer-filter. Ze zien dus niet exact hetzelfde op hetzelfde moment.

Ik corrigeer dit door de rode en blauwe kanalen handmatig te verschuiven zodat ze uitlijnen met het groene kanaal. Omdat de lijnen gelijkmatig verdeeld zijn, kan ik ze in tegenovergestelde richtingen verschuiven.

Weergave

Het delen van deze beelden is lastig vanwege de enorme afmetingen. De meeste software kan hier niet tegen. Voor de browser heb ik het project OpenSeadragon gebruikt, wat een makkelijke manier biedt om in beelden te zoomen. Met de vips-utility heb ik de grote TIFF-bestanden opgedeeld in kleine JPEG-tegels.

Toekomstig werk

Ik heb diverse plannen voor de toekomst:

  • De camera onafhankelijk maken van de laptop, zodat het minder opvalt en makkelijker mee te nemen is.
  • De nabewerkings-tools verbeteren, inclusief een GUI om segmenten te markeren en previews te bekijken met verschillende afstand-per-pixel waarden.
  • Experimenteren met infraroodfotografie en kleurwisselingen in de stijl van ærochrome.
  • De mapping tussen de gain-instelling van de camera en ISO vaststellen, zodat ik locaties kan verkennen met een lichtmeter.

Code

De code voor de acquisitie is beschikbaar op [deze link] en de postprocessor (grindstone) op [deze link].

Erkenningen

Mijn dank gaat uit naar:

  • Meadow (mee-rijden, presentatie, proofreading)
  • Brooke (mechanisch ontwerp, 3D-printen)
  • Ari (mee-rijden, code, presentatie, proofreading)
  • nyanotech (mee-rijden)
  • cat (mee-rijden)
  • Maddie (code, mee-rijden, proofreading)
  • kim (proofreading)