Home sweet home
Nav
hide
S1
S2
S3
Name: insertPhotoWaypoints
Typ: bash
benötigt: exif (lese Exif-Informationen)

Viele Kameras speichern Datum/Uhrzeit, nicht aber die Position per gps. Anhand der Uhrzeit können mit Hilfe des Scripts Wegpunkte in einen GPX-Track eingefügt werden, so dass mit einem entsprechenden Programm (hier Jürgen Berkemeiers Script GPX Viewer) der Track mit Fotos angezeigt werden kann.

Das Script liest eine gpx-Datei und sucht in den trackpoints nach einem Datum, dass möglichst nah an der exif-Information der Fotos liegt Ich verwende das Tag DateTimeOriginal, da dies von meiner Kamera geliefert wird (eventuell ist hier eine Anpassung des Scripts fuer andere Kameras nötig). In die gpx-Datei wird dann ein waypoint aufgenommen, der den Namen des Fotos traegt.
Die originale gpx-Datei wird als backup gespeichert.

Da ich direkt beim ersten Versuch eine Abweichung von einer Stunde hatte (MEZ vs UTC), wird ein Zeit-Shift eingebaut. Das Datum des Fotos wird fuer die Berechnung veraendert. GPS-Daten sind laut wikimedia in utc angegeben, wie eine Kamera speichert weiss ich nicht, daher ist die Korrektur vorgesehehen. Die Angabe ist in Stunden oder in Sekunden möglich. (Sekunden, falls die Uhrzeit eines der Geräte nicht stimmt.)

Beispielaufruf: insertPhotoWaypoints.sh 2013-08-01-Donnerstag*jpg 2013-08-01-Felsentor.gpx

Der Quelltext:

hide
insertPhotoWaypoints.sh
#!/bin/bash
# KR - q&d, 2014-01-02
function abs ()
{
    declare -i res
    res=$1
    if [[ $res -lt 0 ]]
    then
        let "res *= (-1)"
    fi
    eval $1="$res"
}
function containsElement () 
{
  local e
  for e in "${@:2}"; do [[ "$e" == "$1" ]] && return 0; done
  return 1
}
echo
echo "Viele Kameras speichern Datum/Uhrzeit, nicht aber die Position per gps"
echo "Dieses Script liest eine gpx-Datei und sucht in den trackpoints nach einem Datum, dass"
echo "möglichst nah an der exif-Information der  Fotos liegt"
echo "Verwende das Tag DateTimeOriginal, da dies von meiner Kamera geliefert wird"
echo "(eventuell ist hier eine Anpassung des Scripts fuer andere Kameras noetig)"
echo "In die gpx-Datei wird dann ein waypoint aufgenommen, der den Namen des Fotos traegt" 
echo "Damit kann das Bild dann von JBs gpxViewer angezeigt werden"
echo "Die originale gpx-Datei wird als backup gespeichert."
echo
echo "Da ich direkt beim ersten Versuch eine Abweichung von einer Stunde hatte (MESZ vs UTC), wird ein Zeit-Shift 
eingebaut. (Eingabe unten). Das Datum des Fotos wird fuer die Berechnung veraendert. 
GPS-Daten sind laut wikimedia in utc angegeben, wie eine Kamera speichert weiss ich nicht, daher ist die 
Korrektur vorgesehehen. Es sind Angaben in Stunden oder Sekunden moeglich, 
da evtl. auch mal die Zeit bei einem der Geraete verstellt ist..."
 
echo
echo "Beispielaufruf: insertPhotoWaypoints.sh 2013-08-01-Donnerstag*jpg 2013-08-01-Felsentor.gpx"
if [[ $# -lt 2 ]]
then
    echo -e "\n -> Fehler: Anzahl Parameter stimmt nicht" 
    exit
fi
nargs=$#
files=("$@")
echo ${files[@]}
gpx=${files[$((nargs-1))]}
unset files[$((nargs-1))]
let nargs--
echo -e "\nBild-Dateien: "  ${files[@]}
echo "GPX-Datei:    "  $gpx
echo "Stundenkorrektur (Berechnung Foto Datum wird geschoben, zb +1 / -1) Stress mit Sommerzeit und so :-) [0]"
echo "Angabe auch in Sekunden möglich, z.B. 1800s oder -1800s (vgl. Delta der Ausgabe) Kommazahlen nicht moeglich"
 
read tshift
if [[ "$tshift". == "." ]]
then
    tshift=0
else 
  right=${tshift:(-1)}
  if [[ $right == 's' ]]
  then
    tshift=${tshift/s/}
    let "tshift *= 1" #sicher int?
  else
    let "tshift *=  3600"
  fi
  echo "Shift in Sekunden: $tshift" 
fi
echo  "Enter: weiter, ctrl-c zum abruch, d -> dry, keine Aenderung, nur Analyse "
read dry
 
#template wegpunkt
wpTemplate='\n
<wpt %pos >\n
<ele>%ele</ele>\n
<time>%datumT%zeitZ</time>\n
<name>%bildName</name>\n
<cmt></cmt>\n
<desc></desc>\n
<sym>Scenic Area</sym>\n
</wpt>\n'
declare -a wpA  
declare -a posA
#datei in array lesen
mapfile -t gpxContent < "$gpx"
#bilder abarbeiten
for b in "${files[@]}"
do
    echo -e "\nBild " $b
    bildDatum=$(exif $b -t DateTimeOriginal | grep -m 1 "Value" | cut -c 10-28)
 
    if [[ $bildDatum"." = "." ]]
    then
        echo $b has no exif - or is actually renamed -  we do nothing
        continue
    fi
 
    datum=${bildDatum/ */}
    datum=$(echo $datum | tr ':' '-')
#bash ersetzt nur ein zeichen?
    zeit=${bildDatum/* /}
    bildDatum="$datum $zeit"
    secondsBildSince1970=$(date -d  "$bildDatum" '+%s')
    if [[ tshift -ne 0 ]]
    then
        let "secondsBildSince1970 += tshift"    
        zeit=$(date -d @$secondsBildSince1970 '+%T')
        datum=$(date -d @$secondsBildSince1970 '+%F')
        bildDatum="$datum $zeit (korrigiert)"
    fi
#echo $secondsBildSince1970
    open=0
#minimalwerte sind die werte deren trackpoint den geringsten zeitlichen Abstand
#vom korrigierten Datum/Zeit des Fotos hat
    unset deltaMin
    unset tmin
    unset positionMin
    unset elevationMin
    for l in "${gpxContent[@]}"
    do
#suche nach trkpt
        if [[ "$l" == *"<trkpt"* ]]
        then
            open=1
            position=${l/*trkpt /}
            position=${position/>*/}
        elif [[ "$l" == *"</trkpt"* ]]
        then
            open=0
        elif [[ "$l" == *"ele"* ]]
        then
            elevation=${l/*<ele>/}
            elevation=${elevation/<*/}
        fi #wenn <trkpt
        if [[ $open -eq 1 ]]
        then
            if [[ "$l" == *"<time>"*"</time>"* ]]
            then #time tag weg
                l=${l/<time>/}
                l=${l/<\/time>/}
                secondsTRKPTSince1970=$(date -d  "$l" '+%s')
                #utc wird beruecksichtigt
                if [ -z $deltaMin ] #unset oder leer
                then
                    let "deltaMin=secondsTRKPTSince1970-secondsBildSince1970"
                    deltaMinSigned=$deltaMin
                    abs deltaMin
                    tmin=$secondsTRKPTSince1970
                    positionMin=$position
                    elevationMin=$elevation
                else
                    let "delta=secondsTRKPTSince1970-secondsBildSince1970"
                    deltaSigned=$delta
                    abs delta              
                    if [[ delta -lt deltaMin  ]]
                    then
                        deltaMin=$delta
                        deltaMinSigned=$deltaSigned
                        tmin=$secondsTRKPTSince1970
                        positionMin=$position
                        elevationMin=$elevation
                    fi #neues deltamin
                fi #deltamin unset  
            fi # time tag gefunden    
        fi #habe einen trkpt 
    done #schleife über alle Zeilen des gpx-Files 
    tmint=$(date -d @$tmin '+%F %T') 
    echo "Bild: $bildDatum und Trackpoint mit geringster Abweichung: $tmint mit Delta: $deltaMinSigned"
#check Position - Manipulation nicht als Funktion hinbekommen, haette besser doch ein php-Script geschrieben
    #bloede trickserei mit . um einen Trennchar zu haben 
    #containsElement ".$positionMin."  "${posA[@]}"
    #echo "contains " $?
#war mal ein Gedanke - verschiebe einen Punkt etwas, wenn er da ist, das ist 
#unsinn. Der wptType in Gpx1.1 bietet vielleicht über das Tag extensions die 
#Einbindung mehrerer Bilder an - lasse das, erlaube mehrere gleiche Wegpunkte un
#passe JBs Code an
#lasse dies mal als Kommentar drin -> kann spaeter mal einem Wegpunkt ggf. mehrere Fotos 
#zuordnen
#    while  containsElement ".$positionMin."  "${posA[@]}"
#    do 
#     lat=${positionMin/*lat=\"/}
#     lat=${lat/\"*/}
#     lon=${positionMin/*lon=\"/}
#     lon=${lon/\"*/} #ok, habe die Zahlen
#     let "r1=$RANDOM%100 - 50" #$RANDOM liefert bis 32767
#     let "r2=$RANDOM%100 - 50"
#     latn=$(echo "scale=10;$lat + $r1/100000" | bc)
#     lonn=$(echo "scale=10;$lon + $r2/100000" | bc)
#     #echo "$lat $latn $lon $lonn"
#     positionMin="lat=\"$latn\" lon=\"$lonn\""
#     #echo $positionMin
#    done
#    posA+=(".$positionMin.")
#    #echo ${posA[@]}
 
#wp-Array
    add=${wpTemplate/\%pos/$positionMin}
    add=${add/\%ele/$elevationMin}
    add=${add/\%bildName/$b}
    add=${add/\%datum/$datum}
    add=${add/\%zeit/$zeit}
    wpA=("${wpA[@]}" "$add")
done #schleife ueber alle Bilder
 
#sicher ist sicher
if [[ $dry"." != "d." ]]
then
  cp --backup=numbered $gpx $gpx".backup"
  #datei neu erstellen
  trkFound=0
  echo -n "" > $gpx
  for l in "${gpxContent[@]}"
  do
    if [[ "$l" == *"<trk>"* && trkFound -eq 0  ]] # waypoints heraus
    then
        trkFound=1
        for wp in "${wpA[@]}"
        do
            echo -e $wp >> $gpx   
        done
    fi 
    echo $l>>$gpx
  done
fi
 
Parsed using GeSHi 1.0.8.6
Download / View Source / Run it   (depends on file type)

Karsten Römke (k Ponkt roemke at gmx in de), Rechtliches, Datenschutz, etc.
Rein private Seite, lediglich eine Spielerei
Last modified: -
Created: 2014-01-02
Reason: Fotos im GPX-Track
Home sweet home