背景
デジカメの時計が狂っていて旅行の写真のタイムスタンプが狂っていてつらいです
2014-10-05 ごろの写真が 2014-09-14 ごろってタイムスタンプがついています><;
誤差の推定
時間を補正しようにもどれだけずれているかわからないと補正できないです。
ここはRuby関係なく、写真のタイムスタンプとライフログを徹底的に突き合わせて誤差を推定します。
今回の決め手になったのは宮島にむかうときのフェリーで厳島神社の大鳥居を撮った時刻と、その写真をとったときにいただろう場所のGPSログのタイムスタンプから推定しました。
フェリーというそれなりの速度で進む乗り物でかつ写真のために特徴的な軌道を描いていたのでかなり特定しやすかったです。
たぶん10秒もずれてないと思います。
foursquareのチェックイン時刻よりは参考になるはず。
pry> camera = Time.parse("2014-09-14 19:19:54")
=> 2014-09-14 19:19:54 +0900
pry> gps = Time.parse("2014-10-05 12:38:12")
=> 2014-10-05 12:38:12 +0900
pry> gps - camera
=> 1790298.0
1790298秒くらいずれていたようです。
方針
さてこれから情報を修正するのですが、以下の2段階でやっていきます。
ファイル名だけ先に修正するのは上のずれがそれっぽいかを他のカメラの写真との前後関係を確認するためです。
- ファイル名の修正
- exif情報の修正
ファイル名の修正
これは非常に簡単
#!/usr/bin/env ruby
require "fileutils"
require "pathname"
require "time"
Pathname.glob("2014-09-*.jpg") do |file|
date = Time.parse(file.basename(".jpg").to_s.gsub(".", ":"))
date += 1790298
to = date.strftime("%Y-%m-%d %H.%M.%S.jpg")
puts "mv #{file} to #{to}"
FileUtils.mv(file, to)
end
exif情報の修正
exif情報の表示みたいなエントリーはqiitaにも多いのですが、編集までやっているのはあまりみないですね。
利用するgem
rubytoolboxやqiitaとかをみると、
- exifr
- mini_exiftool
あたりがポピュラーなんでしょうか。
exifrは書き込みができないっぽいので、mini_exiftoolを使います。
mini_exiftoolはexiftoolというツールのラッパーとなっています。
exiftoolはhomebrewからインストールするか、mini_exiftool_vendoredを使えばツールもバンドルされています。
まぁこういうバンドル系のgemは一回限りの利用であれば使ってもいいかもしれないですね。
今回はmini_exiftoolを使いました。
$ brew install exiftool
$ gem install mini_exiftool
修正すべきexif情報
そもそも修正すべきexif情報はなんだろうか、exiftoolを使ってちょっと確認してみます。
$ exiftool 2014-10-05\ 12.23.51.jpg | grep 2014
File Name : 2014-10-05 12.23.51.jpg
File Modification Date/Time : 2014:09:14 19:05:33+09:00
Modify Date : 2014:09:14 19:05:33
Date/Time Original : 2014:09:14 19:05:33
Create Date : 2014:09:14 19:05:33
Ricoh Date : 2014:09:14 19:05:33
うーんよくわからないけど、Date/Time Original
をいじればいいのかな?(ひどい)
mini_exiftoolを使った撮影日時の取得
require "mini_exiftool"
photo = MiniExiftool.new("2014-10-05 12.23.51.jpg")
p photo.date_time_original # => 2014-09-14 19:05:33 +0900
timeクラスのインスタンスの入出力でよさそう。
mini_exiftoolを使った撮影日時の更新
timeクラスなんで、さっきと同じdiffを単純に足すだけでもよいんだけど、ファイル名を正としてexif情報を更新するような感じにしたてました。冪等になるので。
#!/usr/bin/env ruby
require "mini_exiftool"
require "pathname"
require "time"
Pathname.glob("*.jpg") do |file|
date = Time.parse(file.basename(".jpg").to_s.gsub(".", ":"))
photo = MiniExiftool.new(file.to_s, ignore_minor_erros: true)
next if photo.date_time_original == date
photo.date_time_original = date
begin
photo.save!
puts "update succeeded for #{file}"
rescue => e
puts e
end
end
で、これを実行してみると、なんかエラーで保存できなくなるのがたまに出てきます。そういうファイルは何度リトライしてもだめ。。こんな感じ。。
MiniExiftool couldn't save. The following errors occurred: (datetimeoriginal) Warning: [minor] Suspicious MakerNotes offset for ManufactureDate1 - /var/folders/13/phlbpvq513jftjmklvqb09rm0000gn/T/mini_exiftool20150805-41691-idw6nz
Error: [minor] Bad MakerNotes offset for Ricoh_Subdir_0x0021 - /var/folders/13/phlbpvq513jftjmklvqb09rm0000gn/T/mini_exiftool20150805-41691-idw6nz
うーんexiftoolが対応しきれてない部分なんかな?それともpicasaがなんかやらかした感じなのかな。。 http://www.sno.phy.queensu.ca/~phil/exiftool/faq.html#Q15
$ exiftool -a 2014-10-05\ 12.38.23.jpg | grep Bad
Warning : Bad RicohSubdir offset for tag 0x0021
Warning : Bad RicohSubdir offset for tag 0x0023
Warning : Bad RicohSubdir offset for tag 0x0026
個人的にはカメラ情報なんてどうでもいいので、削除しますか。。
MakerNotesの削除
コマンドライン的には、
$ exiftool -MakerNotes= 2014-10-05\ 12.38.23.jpg
なんだが、たくさんあるので、例外発生したらMakerNotesも削除して保存するようなコードにします。さっきのrescue以下をこう書き換えます。
rescue
begin
photo.revert
photo.maker_notes = nil
photo.date_time_original = date
photo.save!
puts "update succeeded for #{file}"
rescue => e
puts e
end
end
一見、 photo.maker_notes = nil
だけで良さそうなのですが、mini_exiftoolは、変更する値ごとにexiftoolを呼び出して、すべての実行が成功した場合のみOKとするような実装になっています。したがって、一旦revertして、変更する値を空にしておいてから初手photo.maker_notes = nil
じゃないとだめというわけです。
いやーここはまった。。