はじめに
複数の画像ファイルに付けたキーワードの総数や、キーワードごとの使用回数を調べるという処理を、Pythonのpyexiv2で書きました。画像ファイルのIPTC情報からキーワードを抽出して、集計してみた記事です。
PythonでIPTCを扱うモジュールには、pyexiv2の他にIPTCInfo3というモジュールもあります。
こちらのモジュールも試してみることにしました。
環境
- OS: Windows 11 Home 22H2
- Python: 64ビット版、3.11.4
モジュールのインストール
pip install IPTCInfo3
複数の画像ファイルにおいて、キーワードごとの出現回数を集計する
pyexiv2で行ったように、基準となるディレクトリ配下のJPEGファイルをすべて読み込み、キーワードごとの出現回数を集計します。
IPTCInfo3を使ったときの注意点は、以下のとおりです。
- ファイルを読み込むたびに型のことで警告を返してくるので、ロガーのログレベルを操作して警告表示を抑制する
- 必須ではないが、何百、何千件というファイルを読み込んだときには気になる。必要に応じて表示の抑制を行う
- IPTCInfo3は各要素をbytes型で返してくる。よって、適時変換を行いながら処理する
# 複数の画像ファイルのキーワードを集計する
# 複数の画像ファイルに付けられたキーワードごとの個数を調べてみる
import datetime
import collections
from iptcinfo3 import IPTCInfo
from glob import glob
from tqdm import tqdm
from pprint import pprint
import logging
# IPTCInfo3では、ファイルを読み込むたびに以下の警告が表示される
# WARNING: problems with charset recognition (b'\x1b')
# この警告を抑制するため、ロガーのログレベルを警告より高いエラーにしておく
iptcinfo_logger = logging.getLogger('iptcinfo')
iptcinfo_logger.setLevel(logging.ERROR)
# 基準となるディレクトリ
base_dir = 'baseDir'
# 基準となるディレクトリ配下にあるJPEGファイルを再帰的に読み込む
glob_dir = glob('%s/**/*.jpg' % base_dir, recursive=True)
all_keywords = []
for file_name in tqdm(glob_dir):
try:
img = IPTCInfo(file_name)
# キーワードのリストを取得するが、各要素はbytes型
keywords = img['keywords']
except Exception as err:
# IPTC情報が読めなかったファイル名とエラー内容を表示
print(f'Error file name: {file_name}')
print(f'Exception: {err}')
continue
# キーワードのリストの各要素をデコードして、改めてリストにする
decode_keywords = [x.decode('utf-8') for x in keywords]
# 全部のキーワードを収めるリストに、デコードしたリストを結合する
all_keywords.extend(decode_keywords)
# collectionsのCounterクラスを用いて、キーワードの出現回数を集計する
coll = collections.Counter(all_keywords)
# 整形して表示する
pprint(coll)
# キーワードの出現回数の結果をファイルに出力する
# キーワード数が多いと画面では見切れてしまうので、必要に応じて
with open(f'aggregate_keywords_iptcinfo3_.txt', 'w', encoding='UTF-8') as f:
pprint(coll, stream=f)
集計結果
pyexiv2と同じように集計できました(pyexiv2とは集計対象のディレクトリを変えています)。
Counter({'屋外': 1972,
'日本': 1851,
'風景': 1753,
'晴れ': 1644,
'青空': 1542,
'空': 1513,
'青色': 1353,
(中略)
'冠水': 1,
'走行注意': 1,
'冠水警報': 1,
'LED': 1,
'警告灯': 1,
'要注意': 1,
'洪水': 1,
'警戒': 1,
'1棟': 1,
'複数棟': 1,
'積雲': 1,
'1羽': 1,
'農村': 1})