Skip to content

Instantly share code, notes, and snippets.

@YSRKEN
Last active July 4, 2020 09:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save YSRKEN/832267d8fb810817ec233bc7f63e54df to your computer and use it in GitHub Desktop.
Save YSRKEN/832267d8fb810817ec233bc7f63e54df to your computer and use it in GitHub Desktop.
ディレクトリ以下のJPEGファイルを自動分析するコード(とりまパナ機のみ対応)
import glob
import os
from pprint import pprint
from typing import Dict, Any
from PIL import Image
from PIL.ExifTags import TAGS
from PIL.MpoImagePlugin import MpoImageFile
# Exif情報を取得するためのシグネチャ
exif_signature = b'Exif\x00\x00'
# DecompressionBombWarning対策
Image.MAX_IMAGE_PIXELS = 1000000000
if __name__ == '__main__':
root_path = 'E:/整理済/画像/・記念/撮影画像まとめ'
lens_focal_count: Dict[str, Dict[str, int]] = {} # lens_focal_count[レンズ名][焦点距離] = 回数
# 再帰的に読み込む
for path in glob.glob(os.path.join(root_path, '**', '*.jpg'), recursive=True):
print(path)
with open(path, 'rb') as f:
# Pillowを使い、焦点距離・メーカー名・メーカーノートを取得する
im: MpoImageFile = Image.open(path)
temp: Dict[str, Any] = {}
for tag_id, value in im.getexif().items():
temp[TAGS.get(tag_id, tag_id)] = value
if 'FocalLengthIn35mmFilm' not in temp or 'Make' not in temp or 'MakerNote' not in temp:
continue
focal_length_by_35 = temp['FocalLengthIn35mmFilm']
maker = temp['Make']
maker_note = temp['MakerNote']
# メーカー名に応じた処理を実施する
if maker == 'Panasonic':
# TIFF IFDの読み込み時、オフセット計算に使用する定数を取得する
raw_data = f.read()
raw_exif_offset = raw_data.find(exif_signature) + len(exif_signature)
# TIFF IFDを順次読み込み、レンズ名に関わるものを検索する
ifd_count = int.from_bytes(maker_note[12:14], byteorder='little')
for i in range(0, ifd_count):
pointer = 12 + 2 + i * 12
ifd_data = maker_note[pointer:pointer + 12]
tag_id = int.from_bytes(ifd_data[:2], byteorder='little')
if tag_id == 0x51:
# 取得処理を実施
lens_name_length = int.from_bytes(ifd_data[4:8], byteorder='little')
lens_name_offset = raw_exif_offset + int.from_bytes(ifd_data[8:], byteorder='little')
lens_name_bin = raw_data[lens_name_offset:lens_name_offset + lens_name_length]
lens_name = lens_name_bin.decode('ASCII').replace('\0', '')
# Dictに記録する
if lens_name not in lens_focal_count:
lens_focal_count[lens_name] = {}
if focal_length_by_35 not in lens_focal_count[lens_name]:
lens_focal_count[lens_name][focal_length_by_35] = 0
lens_focal_count[lens_name][focal_length_by_35] += 1
# 集計処理を実施
lens_count: Dict[str, int] = {}
all_count = 0
for lens_name, data in lens_focal_count.items():
if lens_name not in lens_count:
lens_count[lens_name] = 0
for focal_length_by_35, count in lens_focal_count[lens_name].items():
lens_count[lens_name] += count
all_count += count
# 結果を出力する
print(f'\n写真枚数:{all_count}\n')
print('レンズ名,使用率(%),焦点距離毎の使用率(%)')
lens_count2 = sorted(lens_count.items(), key=lambda x: x[1], reverse=True)
for lens_name, count in lens_count2:
print(lens_name, end=',')
print(round(100.0 * count / all_count, 1), end=',')
focal_count = sorted(lens_focal_count[lens_name].items(), key=lambda x: x[1], reverse=True)
for focal_length_by_35, count2 in focal_count:
print(f'{focal_length_by_35}mm({round(100.0 * count2 / count, 1)}) ', end='')
print('')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment