8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

デジカメの日付が狂っていて写真のexif辛い問題をRubyで処理

Last updated at Posted at 2015-08-04

背景

デジカメの時計が狂っていて旅行の写真のタイムスタンプが狂っていてつらいです

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段階でやっていきます。
ファイル名だけ先に修正するのは上のずれがそれっぽいかを他のカメラの写真との前後関係を確認するためです。

  1. ファイル名の修正
  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じゃないとだめというわけです。

いやーここはまった。。

8
9
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
8
9

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?