Python – ディレクトリ内のファイルに同じ処理を行う方法

目次

概要

ディレクトリ内の画像をすべてリサイズしたいといった、あるディレクトリ内のファイルに同じ処理を行いたいというケースに使えるコードを紹介します。

ディレクトリ内の特定の拡張子のファイルを列挙する

あるディレクトリ内の特定の拡張子のファイルを列挙するコードを記載します。

In [1]:
from pathlib import Path


def get_paths(input_dir, exts=None):
    paths = sorted([x for x in input_dir.iterdir()])
    if exts:
        paths = list(filter(lambda x: x.suffix in exts, paths))

    return paths


# ディレクトリ内の指定した拡張子のファイルをすべて取得する。
input_dir = Path(r"/data/samples")
for path in get_paths(input_dir, exts=[".jpg", ".jpeg", ".png"]):
    print(path)

指定ディレクトリ内の画像をリサイズして、別のディレクトリに保存する

先程のコードを利用して、あるディレクトリ内のすべての画像をリサイズして、別のディレクトリに保存するコードになります。

In [2]:
import cv2

from pathlib import Path


def get_paths(input_dir, exts=None):
    paths = sorted([x for x in input_dir.iterdir()])
    if exts:
        paths = list(filter(lambda x: x.suffix in exts, paths))

    return paths


# ディレクトリ内の指定した拡張子のファイルをすべて取得する。
input_dir = Path(r"/data/samples")

# 出力先のディレクトリを作成する。
output_dir = Path(r"output")
output_dir.mkdir(exist_ok=True)

for path in get_paths(input_dir, exts=[".jpg", ".jpeg", ".png"]):
    # 画像を読み込む。
    img = cv2.imread(str(path))
    # リサイズする。
    dst = cv2.resize(img, (300, 300))
    # 結果を保存する。
    save_path = output_dir / path.name
    cv2.imwrite(str(save_path), dst)

指定したディレクトリ内のファイルを再帰的に取得する

あるディレクトリの直下にあるファイルだけでなく、入れ子になったディレクトリ構造のすべてのファイルを再帰的に取得する場合は ` をimg_dir.glob(“*/“)` に変えます。

In [3]:
from pathlib import Path


def get_paths(input_dir, exts=None):
    paths = sorted([x for x in input_dir.glob("**/*")])
    if exts:
        paths = list(filter(lambda x: x.suffix in exts, paths))

    return paths


# ディレクトリ内の指定した拡張子のファイルをすべて取得する。
input_dir = Path(r"sample")
for path in get_paths(input_dir, exts=[".jpg", ".jpeg", ".png"]):
    print(path)

concurrent.futures を使った処理の並列化

各々のファイルに対して行う処理が独立している場合、並列化することで処理時間を短縮できます。 並列化には concurrent.futures を利用します。

Python – concurrent.futures を使った並列化の方法について – pystyle

In [4]:
from concurrent import futures
from pathlib import Path

import cv2


def get_paths(input_dir, exts=None):
    paths = sorted([x for x in input_dir.iterdir()])
    if exts:
        paths = list(filter(lambda x: x.suffix in exts, paths))

    return paths


# ディレクトリ内の指定した拡張子のファイルをすべて取得する。
input_dir = Path(r"/data/samples")

# 処理対象のファイル一覧を取得する。
input_paths = get_paths(input_dir, exts=[".jpg", ".jpeg", ".png"])

# 出力先のディレクトリを作成する。
output_dir = Path(r"output")
output_dir.mkdir(exist_ok=True)


def process(path):
    """処理内容を関数にまとめる
    """
    # 画像を読み込む。
    img = cv2.imread(str(path))
    # リサイズする。
    dst = cv2.resize(img, (300, 300))
    # 結果を保存する。
    save_path = output_dir / path.name

    return cv2.imwrite(str(save_path), dst)


with futures.ThreadPoolExecutor() as executor:
    rets = executor.map(process, input_paths[:10])

# 結果を受け取る。
print([x for x in rets])
[True, True, True, True, True, True, True, True, True, True]

複数の引数を渡したい場合は、ThreadPoolExecutor.map() の代わりに ThreadPoolExecutor.submit() をお使いください。この記事で解説しています。

コメント

コメントする

目次