Script pour faire du reverse geocoding sur vos photos

21 novembre 2007

Avoir les coordonnées GPS dans les entêtes de vos photos, c'est chouette. Mais il faut avouer que pour faire des recherches, c'est loin d'être pratique. Il serait plus pratique de pouvoir chercher le nom de villes ou villages. Heureusement, il existe le reverse geocoding.

Le reverse geocoding ou geonaming consiste à déduire, à partir d'une coordonnée GPS, le nom du village le plus proche. Le site geonames.org propose gracieusement une API permettant d'effectuer cette tâche.

Pour me faciliter la tâche, et exécuter l'opération de reverse geocoding sur l'ensemble de mes photos, j'ai écris un petit script Perl. Ce dernier récupère les coordonnées GPS dans les entêtes EXIF des photos, puis insère la ville correspondante dans le champ city de l'entête IPTC. Ce champ n'est pas visible sous Picasa mais Picasa le prend quand même en compte lorsque vous faite une recherche.


$ecrase_city = 0; #Ecraser ville si déjà renseignée ? (0 = non, 1 = oui)
$max_dist = 3; #Distance max entre photo et village (en km)

$dir = ".";

use File::Find;
use Image::ExifTool qw(:Public);
use Geo::GeoNames;

find(\&Geoname, $dir);

sub Geoname {
/\.[jJ][pP][gG]$/ or return;
$filename = $_;
print $filename."\t";
my $exifTool = new Image::ExifTool;
$exifTool->Options(CoordFormat => '%.6f');
$success = $exifTool->ExtractInfo($filename, \%options);
if (!$success) {
print "Erreur de lecture !\n";
} else {
$city = $exifTool->GetValue('City');
if (($city ne '') && (!$ecrase_city)) {
print "Champ \"city\" plein : $city.\n";
} else {
$lat = $exifTool->GetValue('GPSLatitude');
$lng = $exifTool->GetValue('GPSLongitude');
if ($lat eq '') {
print "Pas de coordonnee GPS.\n";
} else {
$lat =~ /((\d|\.)*)\s(\w)/;
$lat = $1;
if ($3 eq 'S') {$lat = -$lat};
$lng =~ /((\d|\.)*)\s(\w)/;
$lng = $1;
if ($3 eq 'W') {$lng = -$lng};
my $geo = new Geo::GeoNames();
$result = $geo->find_nearby_postalcodes(lat => $lat, lng => $lng);
$name = $result->[0]->{'name'};
$dist = $result->[0]->{'distance'};
if ($dist > $max_dist) {
printf("$name trop loin (%.2f km).\n",$dist);
} else {
$exifTool->SetNewValue('city', $name);
$success = $exifTool->WriteInfo($filename);
if (!$success) {
print "Erreur d'enregistrement !\n";
} else {
print "$name\n";
}
}
}
}
}
}


Il nécessite :
- L'installation d'un interpréteur Perl bien sûr. Pour les utilisateurs de Windows, je vous propose ActivePerl ;
- L'installation de la librairie ExifTool ;
- L'installation de la librairie Geonames.

Pour installer ces librairies, il suffit de décompresser le contenu des répertoires "lib" des archives dans le répertoire "lib" de Perl.

Ce script a quelques défauts, liés au service geonames.org. Premièrement, le nom des lieux ne comprend pas d'accents ni de tirets. Deuxièmement, lorsque vous êtes en périphérie d'une grande ville, il est possible que le centre du village le plus proche ne soit pas la grande ville mais un petit village de banlieue. Troisièmement, geonames.org m'a déjà répondu des absurdités ("Ile-de-Sein" pour une coordonnée à côté de "Concarneau").

Pour lancer le script, copiez le code dans un fichier .txt dont vous aurez changé l'extension en .pl puis placez-le dans le répertoire de votre album photo. Enfin, lancez-le (avec ActivePerl, il suffit normalement de double-cliquer sur le fichier).

0 commentaires: