Pythonでexif(Jpegの撮影日など)を取得する

 

Jpegには写真の撮影日やカメラの機種名など保存されている。
これはexifという仕組みで、スマホのアルバムなどにはなくてはならない仕組み。

うちの写真類はHDDにどんどんコピーしていって、同じディレクトリに数万ファイルある状態になってしまって
完全にものを探せる状態じゃない。
というわけで撮影日を一覧で取得するものを書いてみた。

必要なライブラリ

Pythonで画像関連を何とかしてくれるライブラリではPILというものがあるのだけれども
Python3には対応していないそうだ。
PILからフォークしたPython3対応のライブラリがpillow
pipからもpillowという名前でインストールができる。

元はPILなので、importなどはPILそのままになっている。

サンプルコード

指定したディレクトリの中にある写真の撮影日と、ファイルのフルパスを標準出力に表示するプログラム。

import os
from PIL import Image
from PIL.ExifTags import TAGS

target_path = "/path/to/photo/dir/"

def get_exif(img):
    exif = img._getexif()
    try:
        for id,val in exif.items():
            tg = TAGS.get(id,id)
            if tg == "DateTimeOriginal":
                return val
    except AttributeError:
        return "NON"

    return "NON"

def list_files(dir,func):
    for file in os.listdir(dir):
        try:
            img = Image.open(dir + file)
        except:
            continue
        datetimeinfo = func(img)
        yield (dir + file,datetimeinfo)
        img.close()

def main():
    for taginfo in list_files(target_path,get_exif):
        print(taginfo)

if __name__ == '__main__':
    main()

撮影日のタグ名はDateTimeOriginalで、それ以外の情報は拾ってきていない。

PIL.Imageが画像ファイルを表すクラスになっていて、
_getexif()メソッドでexifの情報が取得できる。
PIL.ExifTags.TAGSで、タグ名がわかりやすい形に変換してくれるらしい

画像ファイルではないものはImage.openで開けないし、
画像ファイルでもexifを持っていないファイルもあるので、
所々に例外処理を入れて、スキップさせている。

他のブログなどでは、Image.openのあとにcloseをしていないけれど、
一応解放はして置かなければ気持ち悪いので、closeしている。

操作感

ウチの画像ファイルはNAS、つまりネットワーク経由の外付けHDDにおいてあり、数万ファイルが一つのディレクトリに押し込められているので、
普通のLinuxコマンドで一覧を取得するにも時間がかかる。

例えばfindコマンドで、拡張子別にフィルタをかけようとしたら、だいぶ待たせられる。
画像ビューワーなどで見ようものなら結構時間がかかる。
こんなにファイルがいっぱいある状態にしなければこんなに困ることはなかったとはおもう。

今回作った奴はかなり早い。

一度ファイルを読み込んで何かをして次のファイルに行くようなことをやったら数十分はかかったけれど、
これは数分もかからなかった。

おそらくこのライブラリはOpenをしても全バイナリは読まないで
必要な情報のみ遅延で読み込むようにしているんだと思う。

参考

http://www.lifewithpython.com/2014/12/python-extract-exif-data-like-data-from-images.html

スポンサードリンク

関連コンテンツ