Märka bilder med GPS-koordinater och platsnamn

Många mobiltelefoner har en GPS-mottagare, och om den är påslagen så sparas koordinaterna automatiskt i varje JPEG-fil. Även en del riktigt dyra digitalkameror har GPS, och kan därmed göra samma sak. (Det handlar förstås inte om att märka bilderna i sig med någon plats, utan om att spara koordinaterna i EXIF-informationen.)

Men jag har ingen sådan digitalkamera, och kameran i min mobil är förfärligt dålig. I det här inlägget berättar jag hur jag själv gjort för att använda GPS-mottagaren i mobilen för att spara platsdata i bilderna från digitalkameran.

För att kunna följa instruktionerna krävs (grundläggande) terminalkunskaper. Du behöver dessutom ha följande program installerade på datorn:

  • Perl. Har du inte redan Perl installerat, så får du själv lista ut hur du ska gå till väga. Du kan kolla om du har Perl genom att helt enkelt öppna ett terminalfönster och kasta upp en enkel trollformel:

    $ echo "print 'Grattis till Perl!\n';" | perl

    Blir du gratulerad är allt grönt.
  • jhead. Krävs egentligen inte, men det underlättar. Kan hämtas härifrån.
  • GPS-mottagare. Självfallet krävs en sådan. Den bör även ha förmågan att spara GPS-data i något filformat. Vilket filformat din mottagare sparar spår i spelar sannolikt ingen roll. Själv använder jag en Android-telefon med programmet My Tracks. (QR-kod finns här.)

Då sätter vi igång!

1. Provpromenad

Det första du behöver göra är att ta en liten provpromenad med kameran och GPS-mottagaren. Spela in promenaden på mottagaren, och ta några bilder på olika platser. När du kommer hem, för över bilderna och GPS-spårfilen till datorn.

2. Spårdata i GPX-format

Om din spårfil är i GPX-format, så kan du hoppa över det här steget. Annars ska du installera programmet GPSBabel, som kan läsa och skriva ett stort antal filformat. Använd programmet för att konvertera din spårfil till GPX.

3. Installera skript för koordinatmärkning av bilder

Programmet som står för märkningen är ett Perl-skript, gpsPhoto.pl. Tanka hem det (»HEAD«-versionen går bra) och installera sedan skriptet så här:

$ sudo mkdir -m0755 /usr/opt /usr/opt/bin
$ sudo install -m0755 gpsPhoto.pl /usr/opt/bin

För att skriptet ska fungera behöver du ett par CPAN-moduler, nämligen XML::Parser och Image::ExifTool. Jag kan inte ett jota om Perl, men ett enkelt sätt att kolla om modulerna är installerade, är att göra så här:

$ echo "use XML::Parser;" | perl

Om ingenting händer, i synnerhet inga felmeddelanden, så är den ena modulen på plats. Är den det inte, kan du installera så här:

$ sudo cpan XML::Parser

Den andra modulen letar du efter på samma sätt:

echo "use Image::ExifTool;" | perl

Och om den inte finns, alltså om du inte får något svar, så installera den så här:

$ sudo cpan Image::ExifTool

Samma kommandon som installerar modulerna, uppdaterar även befintliga installationer till den senaste versionen.

4. Lista ut offset mellan kameran och GPS-koordinaterna

Det här är litet lurigt. I normalfallet sparas GPS-spår nämligen med tider i UTC, alltså vad klockan hade varit om du befunnit dig i Storbritannien, och det hade varit normaltid (»vintertid«). Det innebär att kameran, om den är inställd på lokal tid, kommer att gå en timme före GPS-spåret vintertid, och två timmar före sommartid.

Men det kan kanske också vara på något annat sätt. Bäst att kolla!

$ grep time Provpromenad.gpx | head -3
<time>2010-10-22T11:10:53Z</time>
<time>2010-10-22T11:10:56Z</time>
<time>2010-10-22T11:11:00Z</time>

De här tidpunkterna jämför vi med tidpunkten från den första bilden, som togs ungefär samtidigt som jag slog på GPS-spårningen. Nu kommer programmet jhead till användning, men du kan förstås använda något annat program istället.

$ jhead P1030762.JPG | grep Date/Time
Date/Time    : 2010:10:22 13:15:52

Enligt kameran, som går rätt, så gick jag alltså ut strax efter klockan 13.00. Följaktligen ligger GPS-datan två timmar efter. Om det nu istället hade varit normaltid för tillfället – och jag inte glömt att ställa om kameran – så hade det bara handlat om en timme istället.

Vi kommer att behöva använda offset-värdet i sekunder. Två timmar är 7200 sekunder, en timme är 3600.

5. Märk bilderna med koordinater

Vi är redan framme vid inläggets höjdpunkt! Det är dags att märka bilderna. För att det hela ska gå smidigt, placera bilderna och GPX-filen i en egen mapp. Sedan är det bara att bränna av följande salva. Se till att du gör det i rätt katalog!

$ gpsPhoto.pl --timeoffset -7200 --interpolate linear --gpsfile Provpromenad.gpx --dir .

Efter att skriptet pratat färdigt, och om ingenting gick snett, så är alla bilder i mappen märkta med koordinaterna för platsen de togs.

Om programmet däremot inte kunde hittas, så har du sannolikt inte katalogen /usr/opt/bin i din $PATH. Lätt hänt, lätt löst:

$ echo 'export PATH=$PATH:/usr/opt/bin' >> ~/.profile

Du behöver därefter logga in igen för att detta ska träda i kraft, eller helt enkelt starta om. En quick fix till dess du loggar ut och in igen är dock möjlig, men kommer bara gälla i det terminalfönster du kör den:

$ export PATH=$PATH:/usr/opt/bin

Försök sedan igen. Om det ändå inte fungerar, ge mig en felrapport så att jag kan uppdatera inlägget!

När bilderna är märkta så vill man gärna se om det fungerat. Vi använder jhead:

$ jhead P1030762.JPG
File name    : P1030762.JPG

GPS Latitude : N 59d 17m 31.2796s
GPS Longitude: E 15d 10m  4.763s
GPS Altitude :  80m
======= IPTC data: =======
Spec. Instr.  : Lat 59.2920221111111, Lon 15.1679896296296 - Bearing: 0 - Altitude: 80m
Record vers.  : 4

Ser man på. :-)

6. Märk bilderna med platsnamn

Detta är en liten bonus. Egentligen är bilderna redan märkta med koordinater, men det kan vara roligt att även märka dem med namnet på platsen i fråga. Något skript för att göra detta har jag inte hittat, men jag lyckades faktiskt knacka ihop ett eget, trots att jag som sagt inte kan ett jota av Perl.

För att använda skriptet behöver du, utöver dem från steg 3, även CPAN-modulerna Image::ExifTool::Location och Geo::GeoNames. Du kan testa om du har dem, samt installera dem, på samma vis som du gjorde i steg 3.

Skriptet för platsnamnsmärkning kan du hämta här, och för att installera det gör du så här:

$ sudo install -m 0755 gpsPlacenamePhoto.txt /usr/opt/bin/gpsPlacenamePhoto.pl

Och sedan kör du det på bildfilerna (om du vågar):

$ gpsPlacenamePhoto.pl *.JPG

Skriptet kommer att berätta vad för koordinater den hittar i varje fil, samt vilken plats den noterar. Plats för varje koordinat hämtas automatiskt från sajten GeoNames.

7. Automatisera!

Det vore jobbigt att behöva köra alla dessa kommandon varje gång ett nytt lass bilder kommit in i datorn och ska märkas. Därför har jag gjort i ordning ett enkelt skalskript som automatiserar det hela. Du kan hämta det härifrån, och sedan installera det så här:

$ sudo install -m 0755 geoTag.txt /usr/opt/bin/geoTag.sh

Skriptet körs med fördel så här enkelt:

$ geoTag.sh *.JPG

Det använder sig av en funktion i gpsPhoto.pl, som med hjälp av GPX-filerna räknar ut hur stor offset du antagligen har. Om din kamera alltid är inställd på lokal tid när du fotograferar, så kommer den saken alltså att skötas automatiskt.

Vidare så använder sig skriptet inte av någon enstaka GPX-fil, utan den använder alla sådana filer som finns i samma katalog som den du kör skriptet från. Om du skulle vilja hämta GPX-filerna ur en annan katalog istället, så kan du ange sökvägen direkt på kommandoraden:

$ geoTag.sh -g ~/gpxdata *.JPG

Du kan även ändra den följande raden i skriptet, för att förvälja en annan katalog:

DEFAULT_GPXDIR=.

Det finns ett par parametrar till du kan använda. Kör geoTag.sh -h för att se dem. Eventuellt kommer jag att utöka skriptet med fler funktioner när jag tycker mig behöva dem.

8. Vad gör jag om kameran gått fel?

Allt är inte förlorat bara för att du glömt ställa in kamerans klocka! Tiden som kameran sparat i bildfilernas EXIF-information kan ändras smidigt som bara den, med redan nämnda jhead.

Om du till exempel glömt att ställa om kameran till normaltid efter den sista söndagen i oktober, så kommer alla bilder att vara märkta en timme in i framtiden, jämfört med tidpunkten de faktiskt togs. Detta löser vi genom att dra tillbaka klockan en timme:

$ jhead -ta -1:00 *.JPG

Om du istället glömt att ställa om till sommartid, eller om du ångrar dig, så kan du göra det omvända:

$ jhead -ta 1:00 *.JPG

Det går också bra att ställa om tiden enstaka minuter, till exempel tre minuter in i framtiden:

$ jhead -ta 0:03 *.JPG

Om du vill korrigera på sekunden, eller om du vill ändra datum helt och hållet, ska du använda ett annat kommando, som tar hänsyn till att månader och år inte fungerar på samma sätt som timmar och minuter.

För att använda kommandot behöver du två tidpunkter. Först den tidpunkt då en bildfil säger att bilden togs, och sedan den tidpunkt då bilden enligt en fungerande klocka faktiskt kom till världen. Principen är den följande:

$ jhead -da VERKLIGT_DATUM-FALSKT_DATUM bild.jpeg

Säg till exempel att den första av ett par hundra bilder i en felande samling togs den 5 oktober 2010, och att kameran märkt samma bild som om den togs den 3 februari 1997 istället. Detta fixar således alla bilder i ett svep:

$ jhead -da 2010:10:05-1997:02:03 *.JPG

Förutsatt att alla bilder är lika fel i tiden som den vi plockade datumen från, kommer de nu att vara rätt igen.

Om inte bara datumet, utan även klockslaget var fel, så kan det också korrigeras. Säg att den där bilden togs klockan 13:11, medan kameran trodde hon var 07:39. Saken är lätt:

$ jhead -da 2010:10:05/13:11-1997:02:03/07:39 *.JPG

Och som utlovat, om du upptäcker att alla bilder behöver förflyttas bara fem sekunder bakåt i tiden, så kan du göra det så här:

$ jhead -da 2010:10:05/12:00:00-2010:10:05/12:00:05 *.JPG

jhead har fler fiffiga funktioner! Har du bilder från flera olika kameror, som på grund av olika form på filnamnen inte visas i kronologisk ordning? Döp i sådana fall om dem till tidpunkten de togs så här:

$ jhead -n *.JPG

Du kan även automatiskt rotera bilder, beroende på hur kameran bestämt att de ska roteras, utan att försämra kvaliteten ens en gnutta. (Försämra kvaliteten gör annars vissa bildprogram när man ger sig i kast med att rotera, och bildvisaren i Windows XP tar till mångas förtret helt bort all EXIF-information.)

$ jhead -autorot *.JPG

Det var allt. :-)