http://blog.livedoor.jp/dankogai/archives/51262202.html
EXIFは何となく知っていましたが、GPS座標も定義されていることには驚きました。
http://en.wikipedia.org/wiki/Exchangeable_image_file_format
http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/EXIF.html
http://cachu.xrea.jp/perl/ExifTAG.html
そこで、私の携帯電話(au Walkman(R) Phone, Premier3 )で撮影した写真から、緯度/経度を抽出し、更に逆ジオコーディングで住所を表示してみました。
尚、exifからの緯度/経度抽出には Image::ExifTool 、逆ジオコーディングには、google map apiを使用しています。
※Image::ExifTool
http://search.cpan.org/perldoc?Image::ExifTool
※google map api
http://code.google.com/intl/en/apis/maps/documentation/geocoding/index.html
#!/usr/local/bin/perl use strict; use warnings; use Encode; use Encode::Guess qw/shift-jis euc-jp utf-8/; use Image::ExifTool; use LWP::UserAgent; use XML::Simple; use Data::Dumper; my $GMAP_API = 'http://maps.google.com/maps/geo?output=xml'; my $GMAP_KEY = ""; main(@ARGV); sub main { my($jpeg_image) = @_; #jpegにあるEXIFに含まれる緯度/経度を抽出 my $lon_lat = get_jpeg_gps_pos($jpeg_image); return undef if (ref($lon_lat) ne "ARRAY" or @$lon_lat != 2); #緯度/経度から逆geocodingで住所を取得 my $geo = reverse_geocode($lon_lat); print $geo; } sub reverse_geocode { my($lon_lat) = @_; my $ua = LWP::UserAgent->new(); my $xml = XML::Simple->new(); my $res = $ua->get("$GMAP_API&key=$GMAP_KEY&q=$lon_lat->[1],$lon_lat->[0]"); unless ( $res->is_success ){ print STDERR "fail http get rev geocode:$lon_lat->[1],$lon_lat->[0]"; return undef; } my $xml_str = $res->content; $xml_str = decode("Guess", $xml_str); my $geo = $xml->XMLin( $xml_str ); if (not defined($geo->{Response}->{Placemark}->{p1}->{address})){ return undef; } return $geo->{Response}->{Placemark}->{p1}->{address}; } #Image::ExifToolで、jpegにあるEXIFに含まれる緯度/経度を抽出 sub get_jpeg_gps_pos { my($image) = @_; my $tool = Image::ExifTool->new; my $exif = $tool->ImageInfo( $image ); my $lon = dms2deg( $exif->{GPSLongitude}); #ex. 10 deg 23' 40.20" E my $lat = dms2deg( $exif->{GPSLatitude}); #ex. 43 deg 43' 24.00" N return undef if (not defined($lon) or not defined($lat)); return [$lon,$lat]; } #緯度/経度を度分秒→度に変換 sub dms2deg { my($dms) = @_; my @dms_elms = $dms =~ /(\d+)\D*(\d+)\D*(\d+\.\d+)\D*([NSEW])/o; return undef if (@dms_elms < 4); my $deg = $dms_elms[0] + $dms_elms[1]/60 + $dms_elms[2]/3600; return $deg * -1 if ($dms_elms[3] eq "S" or $dms_elms[3] eq "W"); return $deg; }
実行結果
??丁目????東恋ケ窪, Kokubunji City, Tokyo Metropolis, Japan
逆ジオコーディングの日本語対応は、まだのようですが、十分使えると言う感じ