Transférer et géolocaliser mes photos : un petit script
En matière de classement des photos, comme dans bien d'autres domaines, j'ai le sentiment de ramer à contre courant. L'heure est à l'utilisation de logiciels graphiques sophistiqués, prenant en charge depuis l'insertion de la carte SD (ou la connexion de l'APN) jusqu'au téléversement sur l'album en ligne. Digikam fait, paraît-il, cela très bien, mais je le trouve trop lourd et d'un emploi mal aisé. Je fondais quelques espoir sur oqapy, malheureusement je ne le trouve plus sur les dépôts Archlinux, même pas dans AUR... J'aime assez gthumb mais il ne sait pas faire tout ça.
Bref, je continue à travailler à la mimine selon un processus bien établi :
- Créer un répertoire au nom significatif tant du point de vue chronologique que géographique (aaaammjj_Localisation)
- Y copier les fichiers JPG et les renommer selon un shéma analogue (aaaammjj_hhmmss_Localisation_NomOriginel.JPG)
- Y copier le ou les éventuel(s) fichiers gpx associés et géolocaliser les images
- Sélectionner, recadrer et éventuellement retoucher les meilleurs clichés avant de les transférer vers notre album Piwigo
Pour renommer les photos j'utilise exiv2 de la manière suivante :
exiv2 -r %Y%m%d_%H%M%S_Localisation_:basename: mv *.JPG
Pour géolocaliser j’utilise Gpscorrelate, que j'ai présenté ici, qui est malheureusement abandonné par son créateur mais a l'avantage de disposer à la fois d'une version graphique et d'une version en ligne de commande.
gpscorrelate -g monFichierTrace.gpx -z [valeur] *.JPG
La valeur à associer à l'option -z est le décalage du fuseau horaire, par exemple +1:00 pour l’heure normale d’Europe centrale (CET : Paris, Bruxelles, Genève…) et +2:00 pour l’heure d’été d’Europe centrale (CEST). Ceci dans la mesure ou l’horodatage des photos est faite en heure locale et celle du GPS en UTC, ce qui est en principe le cas. Il y a d'autres options possible, voir la documentation.
Bon, ce n'est pas trop compliqué, mais il faut se souvenir des options, tout ça.... Pourquoi ne pas automatiser le processus dans un petit script ?
#! /bin/bash ####################### ## photoman ## ## interface à exiv2 ## ## et à gpscorrelate ## ####################### declare -i nbRep=0 declare -i nbPhotos=0 declare -A DateTab # chemin du répertoire photo photoRep="/media/NAS/Public/Photos/" # chemin du GPS GPS="/run/media/vincent/GARMIN/Garmin/GPX" IFS=$'\\n' shopt -s nullglob # détection du GPS if [ -d $GPS ]; then find $GPS -iname "*.gpx" > /tmp/tracesGPS if [ $(wc -l /tmp/tracesGPS | cut -d " " -f 1) != 0 ]; then echo read -n 1 -s -p "un ou plusieurs fichiers gpx ont été trouvé dans le GPS. Les copier dans le(s) répertoire(s) photos [O/n] ? " copieTrace copieTrace="${copieTrace:=o}" case $copieTrace in o|O|y|Y ) Geolocalisation=true;; * ) Geolocalisation=false;; esac fi else read -n 1 -s -p "Le GPS n'a pas été détecté : continuer quand même [o/N] ? " question question="${question:=n}" case $question in o|O|y|Y ) Geolocalisation=false ;; * ) exit;; esac fi echo #traitement des photos for fichier in * do if [ ! -f $fichier ]; then continue; fi MimeType=$(file --mime-type $fichier) if [[ ${MimeType:(-10)} != "image/jpeg" ]]; then continue; fi datePhoto=$(exiv2 -g Exif.Photo.DateTimeOriginal $fichier | sed -r 's/^ *//;s/ {1,}/ /g'| cut -d " " -f 4 | sed 's/://g') repertoire=$photoRep${datePhoto:0:4}"/" if [ -z ${DateTab[$datePhoto]} ]; then echo read -p "Veuillez indiquer une localisation correspondant à la journée du $datePhoto puis appuyez sur [Entrée] : " localisation echo DateTab[$datePhoto]="_"$(echo $localisation | sed 's/ /-/g') mkdir $repertoire$datePhoto${DateTab[$datePhoto]} 2> /dev/null ((nbRep++)) # copier les fichiers gpx if $Geolocalisation; then while read line do cp $line $repertoire$datePhoto${DateTab[$datePhoto]} done < /tmp/tracesGPS fi fi fichierRenomme=$repertoire$datePhoto${DateTab[$datePhoto]}"/"$(echo $fichier | sed 's/ /-/g') cp $fichier $fichierRenomme ((nbPhotos++)) exiv2 "-r%Y%m%d_%H%M%S"${DateTab[$datePhoto]}"_:basename:" mv $fichierRenomme done #Bilan if [ $nbPhotos -eq 0 ]; then echo echo "Il n'y a aucune photo à transférer dans ce répertoire" echo "+++++++++++++++++++++++++++++++++++++++++++++++++++++" echo exit fi echo "$nbPhotos photos ont été transférées dans $nbRep répertoire(s)." printf '\\033[7m' read -n 1 -s -p "===> Supprimer toutes les photos dans le répertoire d'origine [o/N] ? " question question="${question:=n}" printf '\\033[0m'echo case $question in o|O|y|Y ) rm -rf *.[jJ][pP][gG] ;; * ) : ;; esac #Géolocalisation if ! $Geolocalisation; then exit; fi read -n 1 -s -p "Géolocaliser les photos transférées [O/n] ? " question question="${question:=o}" case $question in o|O|y|Y ) : ;; * ) exit;; esac for i in "$" do cd $photoRep${i:0:4}"/"$i${DateTab[$i]} for f in "*.[gG][pP][xX]" do gpxFileDate=$(xml_grep 'trkpt' $f --nb_results 1 | xml_grep 'time' --text_only) UTCHour=$(date -d $(echo $gpxFileDate | sed "s/T/ /g" | sed "s/Z//g") +%k | sed "s/ //g") LocalHour=$(date -d $gpxFileDate +%k) TimeZone=$(( $LocalHour - $UTCHour )) gpscorrelate -g $f -z $TimeZone *.[jJ][pP][gG] done done
Quelques explications :
Les premières lignes servent de fichier ini : emplacement du répertoire photo et point de montage du GPS
Ensuite je détecte si le GPS est connecté et je vérifie (find -iname *.gpx) et s'il y a une (ou plusieurs) traces. On y reviendra plus tard
Puis pour chaque fichier du répertoire en cours- je teste s'il est de type image jpg,
- j'extrais la date de prise de vue grace à exiv2
- s'il n'existe pas je crée un répertoire correspondant à cette date (localisation demandée), j'y copie les éventuelles traces du GPS et j'incrémente un compteur (les noms des répertoires sont stockés dans un tableau associatif date => _localisation )
- J'y copie le fichier photo, le renomme (aaaammjj_hhmmss_localisation_nomOririnel.JPG) et incrémenter un compteur
Les trace gpx sont des fichiers XML. On peut évidement les exploiter à la hussarde à grand coup de sed ou de awk, mais un bon parseur vous facilitera la tache. J'utilise ici xml_grep fourni par le paquet perl-xml-twig (Archlinux) ou xml-twig-tools (Debian/Ubuntu). Il me permet ici d'extraire l'horodatage (UTC) du premier trackpoint, que j'exprime en heure locale pour calculer la différence.
J'appelle enfin gpscorrelate pour chaque fichier gpx, avec le décalage horaire calculé, et je l'applique à toutes les photos. En principe une photo n'est concernée que par une seule trace mais s'il arrivait que le fichier JPG contienne déjà des données exif gps elles ne seraient pas écrasées et un message d'erreur serait affiché.
Naturellement ce script ne répond précisément qu'à mes besoins personnels et probablement pas aux vôtres mais il démontre, je l'espère, qu'il n'est pas si difficile de réaliser soi-même l'application correspondant à ses desiderata.