みなさん、写真撮ってますか?
474回 ではUbuntu上での写真の管理現像アプリとしてdarktableを紹介しました。この記事ではdarktableの様々な機能を紹介しましたが、その中にコレクションという写真の検索、絞り込み機能がありました。
フィルムロールに登録された写真を、さらに細かい条件によってフィルタできます。このフィルタを「コレクション」と呼びます。具体的には「撮影日」「 撮影者」「 使ったレンズ」「 焦点距離」「 絞り」「 ISO感度」といったパラメータで絞り込めます。たとえば「PENTAX K-1で今日撮影した写真のうち、ISO感度が3200で絞りがF2.8のもの」といった条件を指定できます。
なぜこのようなことが可能なのかと言えば、デジタルカメラで撮影した写真には画像情報の他に、撮影時の様々な情報がメタデータとして記録されているからです。今回はこうした写真のメタデータをコマンドラインから操作するツールと、その応用例を紹介します。
Exifデータとは?
こうしたメタデータはExif(エグジフ)データと呼ばれています。ExifはExchangeable image file formatの略で、写真用メタデータを画像ファイル(JPEGやTIFF)に埋め込むための規格です。Exifには撮影したカメラのメーカー、モデル、使用したレンズといった機材の情報をはじめ、撮影日時、シャッタースピード、絞り値、フラッシュ使用の有無といった撮影時の設定など、非常に多くの情報が含まれています。
写真の管理アプリといえばAdobe Lightroomが有名ですが、Lightroomもこうした情報をデータベースに格納することで、写真の検索や絞り込みを実現しています[1] 。
[1] 余談ですがLightroomのカタログファイルはSQLite3のデータベースそのものです。Lightroomが手元にある方は、一度sqlite3コマンドで内部を見てみると面白いと思います。筆者はsqlite3コマンドを使ってカタログ内から条件に合致した写真のみを選別し、クラウドストレージにバックアップするという作業を自動化しています。
Exifデータを調べるには
実際に写真に記録されたExifデータを見てみましょう。一番簡単な方法は「ファイル」( ※2 )を使う方法です。JPEGファイルを右クリックしてプロパティを開き、「 画像」タブをクリックしてください。
図1 撮影に使用したカメラメーカーや機種、撮影時の設定など、Exifデータの中でも参照される頻度の高い基本的な情報が表示される
「画像ビューアー」では、もう少し詳しい情報を閲覧できます。JPEGファイルをダブルクリックして画像ビューアーで開いたら、ウィンドウ右上のハンバーガーメニューからプロパティを開いてください。「 メタデータ」タブでは先ほどとほぼ同様の情報しか表示されませんが、「 詳細」タブでは画像に埋め込まれているExif情報をより詳しく表示できます。
図2 画像ビューアーで写真のメタデータを表示した例
図3 「 詳細」タブではこれだけのExif情報を表示できる
このような画像を閲覧するアプリで、付随する情報を表示できるのは言ってみれば当然です。しかし我々としては、コマンドラインからExif情報を取得し、数値や文字列としてプログラムの中で再利用したいですよね。
画像のデータを表示するコマンドと言えば、ImageMagickに含まれているidentifyコマンドが有名です。画像のフォーマット、サイズ、色数といった基本的なデータを一行で表示するidentifyコマンドですが、「 -verbose」オプションをつけて実行するとより詳細な情報を表示できます。
identifyコマンドであるファイルの詳細情報を表示した例。Properties以下にexif:というプレフィックスつきでExifタグとその値が表示されている
$ identify -verbose (ファイル名)
Image: (ファイル名)
Format: JPEG (Joint Photographic Experts Group JFIF format)
Mime type: image/jpeg
(...略...)
Properties:
exif:DateTime: 2019:01:09 19:19:24
exif:DateTimeDigitized: 2018:06:11 18:39:53
exif:DateTimeOriginal: 2018:06:11 18:39:53
(...略...)
-verboseオプションをつけると非常に大量の情報が表示されます。そのままでは使いにくいため、自分にとって必要なタグだけを抜き出しましょう。パイプでgrepコマンドに繋いでもよいのですが、identifyコマンドはformatオプションを指定することで、表示されるタグを絞り込むことができます。たとえばExifデータからカメラのメーカー(exif:Make)とモデル(exif:Model)を表示するには以下のようにします。
(「%[]」で表示させたいタグを囲んで指定する。タグにはワイルドカードが指定できるため、たとえば%[EXIF:GPS*]と指定すると、GPS関連のタグを表示できる)
$ identify -format "%[exif:Make]\n%[exif:Model]\n" (ファイル名)
RICOH IMAGING COMPANY, LTD.
PENTAX K-1 Mark II
このように、Exifデータを参照するだけならばImageMagickでも十分です。しかしImageMagickではExifデータの削除や編集がやりにくいため[3] 、exiftoolというExifの操作に特化したツールを利用するのがおすすめです。
[3] 「convert -strip」コマンドでExifデータの削除は可能ですが、すべてのメタデータを一括削除してしまうため、柔軟性に欠けます。また存在しないExifタグを新規に追加することができません。
exiftoolを使う
「libimage-exiftool-perl」パッケージをインストールしてください。このパッケージはその名の通りExifデータを読み書きするためのPerlライブラリなのですが、コマンドラインインターフェイスとして「/usr/bin/exiftool」というPerlスクリプトが同梱されているため、Perlの知識がなくてもシェルからExifを操作するコマンドとして利用できます。
exiftoolのインストール
$ sudo apt install libimage-exiftool-perl
基本的な使い方はidentifyコマンドと同じで、引数にファイルを渡すだけです。以下のようにタグ名と値がコロン区切りで表示されます。
exiftoolでExifデータを表示する例
$ exiftool (ファイル名)
ExifTool Version Number : 10.80
File Size : 31 MB
File Permissions : rw-rw-r--
File Type : JPEG
Camera Model Name : PENTAX K-1 Mark II
(...略...)
identifyコマンドと同様、デフォルトでは表示される項目が多すぎて使いづらいでしょう。exiftoolではハイフンに続いて表示させたいExifタグ名を指定して、項目をフィルタします。これは複数同時に指定できます。
撮影に使用したカメラとレンズのみを表示する例
$ exiftool -Model -Lens (ファイル名)
Camera Model Name : PENTAX K-1 Mark II
Lens : HD PENTAX-D FA 15-30mm F2.8ED SDM WR
exiftoolはデフォルトで、人間にとって読みやすい形式に変換した上で値を出力します。「 -n」オプションをつけると、この変換を抑制します。
レンズ情報を出力させた例。デフォルトではズーム範囲や開放F値がカメラのカタログと同等の文字列に変換されているが、-nオプションをつけると数値のまま表示される
$ exiftool -LensInfo (ファイル名)
Lens Info : 15-30mm f/2.8
$ exiftool -n -LensInfo (ファイル名)
Lens Info : 15 30 2.8 2.8
「-b」オプションを指定すると、タグ名を省略したバイナリ形式で出力できます。タグ名とこのオプションを指定することで、純粋な値のみを抜き出せるため、スクリプト内では主にこの形式を利用することになるでしょう。たとえば以下のスクリプトは、Exifデータから緯度と軽度の値を抜き出し、Google Mapsに引数として渡すことで、撮影地にピンを立てて表示する例です[4] 。位置情報を記録したスマホの写真などで試してみてください[5] 。
[4] デフォルトで緯度/経度は度、分、秒の60進数の文字列で表示されてしまいますが、Google Mapsでは10進数の小数で指定する必要があるため、「 -n」ないし「-b」オプションが必須です。また緯度/経度を表すGPSLatitude/GPSLongitudeの他に、北緯/南緯を判断するGPSLatitudeRef、東経/西経を判断するGPSLongitudeRefというExifデータも存在します。しかしこれらはGPSLatitude/GPSLongitudeの正負で判断できる(南緯、西経の場合は負数になる)ため、別途参照する必要はありません。
引数に指定したファイルからGPSの緯度、軽度情報を抜き出し、Google Maps上で表示する
#!/bin/bash
Latitude=$(exiftool -b -GPSLatitude $1)
Longitude=$(exiftool -b -GPSLongitude $1)
x-www-browser "https://www.google.com/maps?q=$Latitude,$Longitude"
筆者はexiftoolを写真の整理に利用しています。Exifには「DateTimeOriginal」という撮影日時を記録するタグが存在しますので、これを頼りに「撮影年-月-日」というフォルダを作り、ファイルを「撮影年-月-日-時-分-秒-オリジナルファイル名」という名前にリネームしています[6] 。
[6] わざわざこのようなリネームを行っているのには理由があります。一般的にデジカメでは「IMGPxxxx.JPG」( xxxxはシャッター回数)のようなファイル名で写真が保存されますが、これだと1日に1万枚以上撮影すると、ファイル名のコンフリクトが起きてしまうためです。サフィックスにオリジナルファイル名を含めているのは、1秒間に複数回のシャッターを切ることが多いため、粒度が秒では不都合があるためです。またファイル名にも日付を含んでいるのは、ファイルだけを別フォルダにコピーした際も時系列順でソート可能にするためです。
指定されたフォルダ内にあるすべての写真をリネームして、撮影日ごとに分類する例
for file in $(find $@ -type f)
do
createdate=$(exiftool -n -b -DateTimeOriginal $file)
date=$(awk '{print $1}' <<< $createdate | tr ':' '-')
time=$(awk '{print $2}' <<< $createdate | tr ':' '-')
if [ ! -d $date ]; then
mkdir $date
fi
mv $file $date/$date-$time-$(basename $file)
done
わざわざExifを見なくても、ファイルのタイムスタンプでいいじゃないかと思う方もおられると思います。しかしファイルのタイムスタンプが、常に撮影日時を指している保証はありません。たとえば撮影時にはRAWデータのみを記録し、後日カメラ内でJPEGに現像を行った場合、JPEGファイルのタイムスタンプはファイルが生成された日時になってしまいます。このようなケースでもExifデータを参照すれば、間違いなく撮影日を特定することができるのです。
同一の写真であっても、撮影時に記録されたRAWデータ(PEF)と後日現像したJPEGファイルはタイムスタンプが異なる。しかしExifを参照すれば、正確に撮影日時を知ることができる
$ ls -l
合計 52840
-rwxrwxrwx 1 mizuno mizuno 44048626 12月 31 13:45 IMGP2687.PEF
-rwxrwxrwx 1 mizuno mizuno 10053304 1月 7 21:00 IMGP2687.JPG
$ exiftool -n -DateTimeOriginal *
======== IMGP2687.PEF
Date/Time Original : 2018:12:31 13:45:16
======== IMGP2687.JPG
Date/Time Original : 2018:12:31 13:45:16
Exifデータを書き込むには
exiftoolでは、Exifデータを書き込むこともできます。例として撮影者を表示する「Artist」タグと、著作権者を表示する「Copyright」タグを書き込んでみましょう。設定したいタグと値をイコールで結んで指定します。この際、変更前のファイルは「元ファイル名_original」という名前で自動的にバックアップが作成されます。
Artist/Copyright両方に筆者の名前を設定した例
$ exiftool -Artist='Hajime MIZUNO' -Copyright='Hajime MIZUNO' (ファイル名)
1 image files updated
図4 exiftoolで著作権情報を追記したJPEGファイルの例
このように、Exifデータは簡単に編集が可能です。撮影時のシャッタースピードなどのデータは編集できませんが、撮影日などは容易に改竄が可能です。ネットにアップされている写真のExifデータは、過信しないほうがよいでしょう。
Exifデータを削除するには
SNSの普及により、写真の公開とプライバシーについては、多くの人が意識するようになってきたと思います。第三者の顔にボカシを入れる作業などは、みなさん違和感なく行っているのではいなでしょうか。しかし、写真の見た目にボカシを入れても、Exifデータではプライバシーが丸見え、というケースもあります。前述のGPSデータなどは最たるもので、自宅の位置が一発でバレてしまう可能性もあります。
図5 Adobe Lightroomの出力ダイアログの例。デフォルトで人物情報とGPS情報は削除した上でJPEGファイルを生成するようになっている
Exifデータは編集するだけでなく、そのタグをまるごと消すこともできます。センシティブな情報は、ネットにアップする写真からは消しておくべきでしょう[7] 。前述のExifデータの書き込み時に、イコールの後の値を空白にすることで、そのタグを削除できます。たとえばArtistタグを削除するには以下のようにします。
[7] 人間だけでなく、動物写真や風景写真でもGPS情報の扱いには気を配るべきだと筆者は考えています。。昨今はSNSの普及で撮影地の情報が拡散するのが早く、特に動物の巣や子供の情報などが拡散されると、翌日には数十人のカメラマンが押しかけるような例も珍しくありません。残念なことに、無断で私有地に入り込んでしまったり、野生動物にストレスを与えてしまうようなケースもあります。
Artistタグを削除する例
$ exiftool -Artist= (ファイル名)
写真から位置に関する情報を消してみましょう。GPSではじまる名前のタグを上述の手順でひとつずつ削除してもよいのですが、以下のコマンドを実行すると一括で削除できます。
$ exiftool -gps:all= (ファイル名)
図6 上記コマンドの実行前後で、exiftoolの出力のdiffを取った例。GPS関連タグだけが綺麗に消えているのがわかる
Exif情報は本格的なデジタル一眼レフに限らず、スマホで撮影した写真にも当然埋め込まれています。ぜひお手持ちのスマホで撮影した写真で試してみてください。