画像がら位置情報を取得する

Hokkaido.pm#4で紹介されてたので、自分でもやってみる。


紹介されていたのは、Image::ExifTool を使った位置情報の取得方法だったが、
天邪鬼な自分は、別のモジュールを使ってやってみる。
とはいっても、Image::EXIF を使うだけなので労力は大して変わらないんですけどね。

まずは、緯度経度を取得し標準出力にだしてみる。

use strict;
use warnings;
use utf8;
use Image::EXIF;

my $exif = Image::EXIF->new;
$exif->file_name( $ARGV[0] );
exit if ( $exif->error );


my $image_info  = $exif->get_image_info();
my ( $lat, $lng ) = ( $image_info->{Latitude}, $image_info->{Longitude} );

print "lat: $lat, lng: $lng\n";

結果

lat: N 43▒ 1' 26.3826, lng: E 141▒ 22' 1.1454

なん…だと…?
まさか文字化けするような文字が含まれてるとは予想もしなかった。

Encodeと、Encode::Guessdを使って文字化けを直す。

use strict;
use warnings;
use utf8;
use Image::EXIF;
use Encode;
use Encode::Guess;

my $exif = Image::EXIF->new;
$exif->file_name( $ARGV[0] );
exit if ( $exif->error );

my $image_info  = $exif->get_image_info();
my ( $lat, $lng ) = ( $image_info->{Latitude}, $image_info->{Longitude} );

my $enc = guess_encoding( $lat, qw/ euc-jp shiftjis 7bit-jis utf8 / );
if ( ref $enc ) {
    $lat = encode( 'utf8', decode( $enc->name, $lat ) );
    $lng = encode( 'utf8', decode( $enc->name, $lng ) );
}

print "lat: $lat, lng: $lng\n";

結果

lat: N 43ー 1' 26.3826, lng: E 141ー 22' 1.1454

やったね。文字化け直ったよ。
ちなみに、shift-jisの、半角長音記号が入っていたらしい。
そんなバカなって気がするんですが、今回は深く追求しません。


せっかくなので、GoogleMapで表示するためのURLにしてみる。
なお、日本測地系になっているので、Location::GeoToolを使い世界測地系に変換している。

use Encode;
use Encode::Guess;
use Location::GeoTool;

my $exif = Image::EXIF->new;
$exif->file_name( $ARGV[0] );
exit if ( $exif->error );

my $image_info  = $exif->get_image_info();
my ( $lat, $lng ) = ( $image_info->{Latitude}, $image_info->{Longitude} );

my $enc = guess_encoding( $lat, qw/ euc-jp shiftjis 7bit-jis utf8 /);
if ( ref $enc ) {
    $lat = encode( 'utf8', decode( $enc->name, $lat ) );
    $lng = encode( 'utf8', decode( $enc->name, $lng ) );
}

my @lat = $lat =~ m{ (\d+) .*? (\d+) .*? (\d+\.\d+) }xms;
my @lng = $lng =~ m{ (\d+) .*? (\d+) .*? (\d+\.\d+) }xms;

my $lgt = Location::GeoTool->create_coord(
    "$lat[0].$lat[1].$lat[2]",
    "$lng[0].$lng[1].$lng[2]",
    'tokyo',
    'gpsone',
);

# 世界測地系へ変換
my ( $wgslat, $wgslng ) = $lgt->datum_wgs84->format_degree->array;

printf( "http://maps.google.co.jp/maps?q=%s,%s&hl=ja\n", $wgslat, $wgslng );

結果

http://maps.google.co.jp/maps?q=43.0264196517887,141.363259066578&hl=ja

とうわけで、出力したURLを入力して実際に見てみると……。
あれ、思ったより位置がずれてる。


試しに、日本測地系のまま出力したURLは以下。

http://maps.google.co.jp/maps?q=43.0239951666667,141.366984833333&hl=ja

こっちのほうが、想定していた場所に近いところを示す。
うーん。なんでだろう……。

想定していた場所はここ。

たまに行ってる回転寿司トリトン。おいしいんだ。