Un script pour les données de géolocalisation dans les photos

J’en parlais dans l’article Zenphoto : Nouveau thème et géolocalisation : j’ai écrit un petit script pour évaluer la quantité de photos incorporant les données GPS (données EXIF).

Le résultat n’est pas fameux d’ailleurs, seulement 10% environ des photos de mon voyage en Asie contiennent ces fameuses données permettant leur géolocalisation. Alors que je les ai toutes prises avec le smartphone… 🙁 Il faudra que je sois plus vigilant lors de mon prochain voyage.

Mais revenons au script Bash : avant tout, je suis loin d’être un pro du Bash, mais j’aime bien me faire de petits scripts qui répondent à mes besoins, comme par exemple analyser le contenu de ma médiathèque (afficher les derniers ajouts, rechercher un mot clef, etc…). Avec l’aide d’internet et à force d’essais, on finit toujours par arriver à ses fins. Et en fait, j’aime bien m’y plonger, je ne vois littéralement pas les heures passer, et quand j’arrive au résultat voulu, c’est toujours gratifiant.

Pour info, voilà le résultat du script quand il analyse le dossier des photos du voyage en Asie : cela vous donne une idée de ce qu’il fait, et du soin que j’ai apporté aux couleurs ! 😉

Le résultat n’est pas fameux ! 10% seulement des photos ont les données GPS…

Voyons voir de quoi est fait ce script : quel outil j’ai utilisé, et les principales étapes du traitement.

L’outil exif

Après une rapide recherche sur le net, j’ai d’abord utilisé l’outil exif mais celui-ci s’est vite révélé peu pratique à manipuler : en effet, il renvoie les données sur stdout si tout va bien, en précisant le nom de fichier :

Les données GPS sont trouvées et affichées, avec le nom du fichier

Jusque là tout va bien. Mais s’il considère les données corrompues, il les renvoie sur stderr sans préciser le nom du fichier ! 😥

Message d’erreur car les données sont manquantes, sans le nom du fichier

À ce stade, je peux encore m’en sortir avec la liste de tous les fichiers comparée à celles des fichiers ayant les données. Mais cela se complique quand je me rends compte que dans certains cas, il affiche le nom du fichier sur stdout ET un message d’erreur sur stderr :

L’outil EXIF envoie un message à la fois sur stdout et sur stderr ! 🙁

Là, je me dis que ça va devenir très compliqué d’utiliser cet outil, qui ne semble pas vraiment abouti.

Donc EXIT EXIF ! ➡ []

L’outil exiftool

Je me tourne alors vers un autre outil : exiftool.

$ sudo apt install exiftool

Il apparaît vite comme extrêmement complet et puissant. Et surtout, les fichiers aux données de géolocalisation indiquées comme « corrompues » par exif ne le sont plus ! Elles sont absentes ou présentes, mais ne génèrent aucun message d’erreur :

Pas de message d’erreur, et le fichier image-04.jpg a bien les données !

À toutes fins utiles, voilà un exemple pour insérer des données EXIF si elles sont manquantes dans les fichiers. Cela m’arrive si je récupère une photo que l’on m’a envoyée par SMS par exemple, ou d’un autre appareil où ces données ne sont pas intégrées pour une raison ou pour une autre. Ici j’insère la position GPS, la date de prise de la photo, ainsi que la marque et le modèle de l’appareil :

$ exiftool -overwrite_original -GPSLatitude="47 deg 54' 45.2" -GPSLongitude="3 deg 58' 25.6" -GPSLatitudeRef="North" -GPSLongitudeRef="West" -DateTimeOriginal="2022:01:10 11:41:06" -Make="bq" -Model="Aquaris X Pro" Image-01.jpg

Ce sont les données dont j’ai besoin pour mon album photo ! L’ensemble des tags sont disponibles sur la page d’Exiftool.

Revenons à notre script : exiftool permet d’exporter les données extraites dans un fichier .csv, qui sera bien plus pratique à traiter dans le script. Comme il est dit sur sa home page : Powerful, fast, flexible and customizable !

Le script

Vous pouvez le récupérer ici, si vous voulez l’utiliser ou vous en inspirer. Je re-précise que c’est du travail d’amateur, qu’il y a sûrement moyen de faire mieux, plus simple, plus court, etc… Le but est avant tout de partager ! 😎

J’ai utilisé des fonctions, cela permet de structurer le code d’une part, et d’éviter de répéter les mêmes lignes d’autre part. Conséquence : puisque l’on définit d’abord les fonctions, il faut aller chercher le début d’exécution du script à la fin (vers ligne 160).

Il y a deux dépendances à installer : l’outil exiftool bien sûr, mais aussi l’outil bc (Bash Calculator) pour pouvoir afficher les pourcentages.

$ sudo apt install exiftool bc

Ces deux dépendances sont testées dans le script de façon assez simple (le « blabla… » est bien entendu un message expliquant comment installer l’outil) :

if ! command -v exiftool &> /dev/null
then
	echo "blabla..."
    exit
fi
if ! command -v bc &> /dev/null
then
	echo "blabla..."
    exit
fi

Puis je teste l’existence du paramètre ($1) que l’on doit passer au script. S’il est bien présent, je le transforme en « chemin absolu » et l’affecte à la variable $dossier.

if [ -z "$1" ] ; then
	echo "blabla..."
	exit
else
	dossier=$(readlink -f "$1")
fi

Et s’il est absent, le « blabla… » ci-dessus est un message d’aide :

Il me faut donc maintenant vérifier les informations de longitude et de latitude les fichiers images du répertoire (et de ses sous-répertoires) passé en paramètre. Une fois les tags GPS de l’outil exiftool identifiés, la commande suivante va me créer le fichier liste.csv à partir duquel je vais pouvoir faire mes calculs, en ne traitant que les fichiers JPG et PNG, et en parcourant les sous-répertoires :

exiftool -ext jpg -ext png -r -csv -filename -GPS:GPSLatitude -GPS:GPSLongitude "$dossier" >> liste.csv

exiftool génère alors un fichier liste.csv avec la virgule comme séparateur, et les données SourceFile,FileName,GPSLatitude,GPSLongitude :

Les fichiers avec ou sans données GPS sont listées, et dans un fichier structuré.

Vient ensuite le traitement de ce fichier, qu’il s’agit de traiter ligne par ligne. J’ai trouvé cette page qui explique bien les différentes possibilités qu’offre le Bash. Ce n’est pas aussi trivial qu’on pourrait le croire, avec notamment le séparateur de fichier interne (IFS) à gérer. Là, avec mon fichier CSV et sa virgule comme séparateur, cela simplifie bien le problème.

J’ai opté pour le « process substitution » car je voulais supprimer la première ligne du fichier CSV avant de le traiter. Il faut aller en bas de la boucle (DONE) pour voir le fichier en entrée à traiter, puis je précise que le séparateur est la virgule, et enfin je recherche les mots clefs ‘latitude’ ou ‘longitude’ (les deux doivent être présents). Ensuite j’incrémente un compteur « nogps » et ajoute les noms de fichiers dans deux fichiers distincts.

while IFS="," read -r source filename latitude longitude
do
  nbreimages=$((nbreimages+1))
  if [ -z "$latitude" ] || [ -z "$longitude" ] ; then
	nogps=$((nogps+1))
	echo "$filename" >> liste_fichiers_noGPS.txt
  else
	echo "$filename" >> liste_fichiers_GPS.txt
  fi
done < <(tail -n +2 ./liste.csv)

Le reste est assez simple : on compte, on ajuste, on calcule... Puis on affiche les résultats, en proposant de sauvegarder les listes dans le répertoire home de l'utilisateur. Puis on efface tous les fichiers qui ont été créés par le script avant de sortir.

Voilà, un petit script bien pratique, même si le résultat n'est pas celui espéré pour mon voyage en Asie ! En tout cas, j'ai bien aimé le réaliser, c'est déjà ça...

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *