デジカメ写真の整理手法とexiv2コマンドの使い方

近ごろはデジタル一眼カメラもコンパクトデジタルカメラも驚くほど安くなりましたし、2010年頃からスマートフォンでもそこそこの画質の写真が撮れるようになりましたから、日々、写真を撮らない人の方が珍しくなったかもしれません。写真を撮り溜めたり交換したりしていると直面するのが写真の整理の問題です。ここでは私が用いているJPEG写真の整理手法をご紹介します。

重要なことのまとめ

重要なことを先に書きます。

  • カメラの時計を合わせる。
  • 写真の連番をリセットせず、SDカードを交換しても続きの番号で保存されるようにする。
  • ジオタグは付加した方が後々楽しい。

将来は優れた写真管理ツールが登場するでしょうし、管理するスクリプトを自分で書く能力も高まることでしょう。ですから最低限、上記だけ守ればあとは何とかなると思います。

JPEGファイルのEXIFフィールドを読んでみる

JPEGファイルには、写真の撮影日付や機材名、そして緯度経度も埋め込まれていることはご存知の方も多いでしょう。JPEGファイルに埋め込まれているこれらの情報をEXIF (Exchangeable image file format)といいます。他にIPTC (International Press Telecommunications Council)というものもあります。カメラの機種や撮影日時や撮影パラメータや緯度経度を記録するのがEXIFで、被写体の説明や撮影場所の詳しい情報などを入力しておくのがIPTCです。

JPEGファイルのEXIF情報やIPTC情報を読み書きするソフトウェアはたくさんありますが、ここではexiv2というコマンドを用います。CentOSのbaseでも用意されているので大抵のLinuxディストリビューションでバイナリパッケージが用意されているでしょう。

exiv2 -pa foo.jpgで、foo.jpgに含まれているEXIF情報とIPTC情報を確認できます。
結果をスクリプトなどに取り込んで機械処理したい場合はexiv2 -Pkv foo.jpgで読むのが良いと思います。

写真の撮影日時を記すタグ

大抵のJPEGファイルには、DateTime、DateTimeOriginal、DateTimeDigitizedの3つのタイムスタンプが埋め込まれていて、どれも同じ日時を指しています。写真が撮影された日時を示すのはDateTimeOriginalです。GIMPなどで写真を編集すると、DateTimeOriginalは保持してDateTimeが変更されます。

これらの日時情報にはタイムゾーン情報が無く、現地時間が保存されます。iPhoneやAndroid端末を持って国外へ行くと、現地でタイムゾーン情報を取得した以降に撮影した写真の日時は現地時間になります。東へ向かって旅行してタイムゾーンを跨ぐと、後に撮影した写真の日時が先の写真よりも前になるので注意が必要です。

スマートフォンでジオタグ有効で撮った写真にはGPSDateStampとGPSTimeStampというタグがあり、UTC時刻が保存されているのでタイムゾーンが判ります。

タイムゾーンを埋め込むためのTimeZoneOffsetというタグもあるのですが、TimeZoneOffsetを埋め込む機種は見たことがありません。

EXIFの日時情報を用いてファイルのタイムスタンプを直す

デジカメ写真をSDカードからコピーした時は写真の撮影日時がファイルのタイムスタンプになっていますが、iPhoneの写真をiPhoto経由で書き出した場合や、メールで写真を貰った場合などにはファイルのタイムスタンプが失われてしまいます。GPSロガーの付属ソフトを使ってジオタグを後から埋め込んだ場合などにもファイルのタイムスタンプが変わってしまいます。しかしJPEGファイル内には撮影日時が埋め込まれていますから、それを用いてファイルのmtimeを直すことができます。

%exiv2 -T rename foo.jpgで、ファイルのmtimeを直します。この時にexiv2が参照するのはDateTimeOriginalです。

exiv2を実行する計算機のタイムゾーンとJPEG内のDateTimeOriginalのタイムゾーンが異なる場合は、TZ=UTC-8 exiv2 -T rename foo.jpgのように実行します。この例では、マレーシア標準時(UTCより8時間進んでいます)で撮影した写真のmtimeを直しています。

写真のファイル名

写真のファイル名を日付や時刻を含むものにリネームしておくと、ファイル名でソートするだけで時系列順に並ぶので便利です。EXIFの日時情報を用いてファイル名をリネームするツールは、Windows用でもありますね。私の場合は、家人が”%Y%m%d%H%M%S_#{comment}”で整理しているのに合わせていますが、14桁の数字が並ぶのは少々見にくいです。これから整理をするのであれば”%Y-%m-%d_%H%M_#{original_filename}_#{comment}”が良いのではないかと思います。例えば、P1020830.JPGというファイルは2013-07-07_1212_P1020830_クアアイナのハンバーガー.JPGという名前にリネームします。

exiv2 -v -t -r "%Y-%m-%d_%H%M_:basename:_クアアイナのハンバーガー" P1020830.JPGで、ファイル名をリネームします。
ブラケット撮影や連写をすると撮影時刻の時分秒が同一の写真が撮れるので、デジカメが付加した連番もファイル名に残しておくのが良いでしょう。また、”%Y-%m-%d_%H%M”をファイル名に付加しておくと、写真の連番が1に戻ってしまった場合などにもファイル名の一意性を保つことができます。

写真の向きを記すタグ

Orientationというタグが写真の縦横の向きを表します。Windowsの画像ビューアなど対応していないソフトウェアもありますが、完全に無劣化で画像を回転できます。1がそのまま、6が時計周りに90度回転、3が180度回転、8が時計周りに270度回転です。デジカメが自動で付加しますが、向き判定が間違っている場合などには上書き変更することができます。

exiv2 -v -k modify -M"set Exif.Image.Orientation 8" P1020830.JPGで、写真の向きを変更します。

写真の撮影者を記すタグ

Copyrightというタグで写真の撮影者を記録します。友だちと一緒に互いのデジカメで写真を撮って、後から一つのフォルダにまとめて入れる場合などには、写真の出処の人をCopyrightに埋め込んでおきましょう。後で整理し直す際などに、Copyrightを埋め込んでおいてよかったと思う時が絶対にあります。

exiv2 -v -k modify -M"set Exif.Image.Copyright person_name" foo.jpgで、Copyrightタグを埋め込みます。

写真のコメントを記すタグ

写真のコメントはUserCommentタグで示します。

exiv2 -v -k modify -M"set Exif.Photo.UserComment パインバーガーのセット 1,150円" P1020830.JPGで、UserCommentタグを埋め込みます。規格上の制限は判りませんが、実装上はUTF-8の文字列を埋め込んでも問題ないようです。

写真の撮影場所や地名を記すタグ

exiv2 -v -k modify -M"set Iptc.Application2.LocationName クアアイナ 青山本店" P1020830.JPGで、撮影場所を埋め込みます。

exiv2 -v -k modify -M"set Iptc.Application2.City 東京都港区南青山5-10-21" P1020830.JPGで、住所を埋め込みます。

写真にジオタグを付加する

JPEGにジオタグが付加されていると、スマートフォンのアルバムソフトでは地図上にピンを置いて表示したり検索したりすることができます。今後も写真管理ツールの発達とともにジオタグの重要性は増すことでしょう。昔の写真にジオタグが付いていると嬉しいものです。

ジオタグの付加方法の例

Mountain View市のコンピュータ歴史博物館のジオタグをfoo.jpgに付加する例です。GPSLatitudeとGPSLongitudeの値は度分秒の有理数です。

exiv2 -M"set Exif.GPSInfo.GPSLatitudeRef N" \
      -M"set Exif.GPSInfo.GPSLatitude 37/1 24/1 513/10" \
      -M"set Exif.GPSInfo.GPSLongitudeRef W" \
      -M"set Exif.GPSInfo.GPSLongitude 122/1 4/1 383/10" \
      foo.jpg

exiv2コマンドに与える度分秒の計算

Googleマップで適当な場所を右クリックして[この場所について]を選択すると、緯度と経度をfloatで取得できます。

35.681884のようなfloatを”35/1 40/1 548/10″のような有理数の文字列に変換する計算方法は、Rubyで表すと以下のようになります。

def Geo_location::float_to_rational(f)
  raise TypeError, f unless ( f.is_a? Float )
  degree = f.to_i
  f -= degree; f*= 60.0
  minute = f.to_i
  f -= minute; f*= 600.0
  second10 = (f + 0.5).to_i
  "#{degree}/1 #{minute}/1 #{second10}/10"
end

exiv2コマンドで得られた度分秒を小数に変換

exiv2 -Pkvで得られる”50/1 5/1 57975/4096″のような有理数の文字列を50.08726501464844のようなfloatに変換する計算方法は、Rubyで表すと以下のようになります。

def rational_to_float(str)
  if ( str.strip =~ /^(\d+)\/(\d+) (\d+)\/(\d+) (\d+)\/(\d+)$/o )
    a = [ $1.to_i, $2.to_i, $3.to_i, $4.to_i, $5.to_i, $6.to_i ]
  else
    raise ArgumentError, str
  end
  # 下の二つの計算式は同じ意味である。上の計算式の方が精度が高そうに思えたが、試したところ有意な精度差が見られなかったので、読みやすい下の計算式を使っている。
  # (3600 * $1.to_f * $4.to_f * $6.to_f + 60 * $2.to_f * $3.to_f * $6.to_f + $2.to_f * $4.to_f * $5.to_f) / (3600 * $2.to_f * $4.to_f * $6.to_f)
  # $1.to_f / $2.to_f + $3.to_f / $4.to_f / 60.0 + $5.to_f / $6.to_f / 3600.0
  a[0].to_f / a[1].to_f + a[2].to_f / a[3].to_f / 60.0 + a[4].to_f / a[5].to_f / 3600.0
end

Googleマップの検索窓に N35.659118,E139.543509 のような緯度経度を入力すると、その座標へ移動します。

海外旅行の写真を整理する際の注意点

デジタルカメラ, GPSロガー, スマートフォンを複数持っていて、同行者もいるという前提で述べます。

  • デジカメの時計は日本時間に合わせて、旅行中もそのままにします。
  • GPSロガーにはタイムゾーンを設定しますが、日本時間のままにします。
  • スマートフォンのジオタグ付加はONにします。

同行者から写真を貰ったら、Copyrightを埋め込みます。

デジカメと対になるGPSロガーの記録を使ってジオタグを埋め込みます。

それぞれの写真のmtimeを直します。デジカメ写真のタイムゾーンは日本時間、スマートフォンの写真のタイムゾーンは飛行機が降りたあたりで切り替わるので注意しましょう。exiv2 -v -t -rの方法でファイル名をリネームしてデジカメ写真とスマートフォンの写真を同一フォルダにコピーすると、ファイル名でソートした時に写真の順序が前後します。exiv2のリネーム機能だと対応できないので適当なスクリプトを書いてリネームするか、あるいはmtimeでソートしましょう。私は、自分でスクリプトを書いて現地時間のファイル名を付けています。

それぞれの写真のmtimeを直しておくと、複数のカメラの写真を同一フォルダにコピーしてもファイルの日付ソートをすると時系列順で並べることができます。

別行動をした場合はフォルダを分けましょう。

ls -lで見えるファイルの日時は日本時間のものです。現地時間での日時を見たい場合はTZ=UTC-8 ls --full-timeのように実行します。

さいごに

exiv2コマンドの使い方を軸に、写真の整理手法をご紹介しました。いかがでしたでしょうか。あまり凝ったことはせず、exiv2 -t -r "%Y-%m-%d_%H%M_:basename:でリネームして月毎にフォルダ分けするだけでも十分だと思います。

本稿が皆様の思い出の記録のお役に立てば幸いです。