Last active
July 4, 2020 09:04
-
-
Save YSRKEN/832267d8fb810817ec233bc7f63e54df to your computer and use it in GitHub Desktop.
ディレクトリ以下のJPEGファイルを自動分析するコード(とりまパナ機のみ対応)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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