Python が大量の画像を処理するときに発生するメモリ不足の問題を要約して解決する

1. 問題点

多数の画像を処理すると、特にすべての画像が同時にメモリに読み込まれる場合、メモリ使用量が高くなる可能性があります。

2. 主な解決策

  1. バッチ処理:画像を小さなバッチに分割して処理し、毎回画像の一部のみを処理し、処理が完了したらメモリを解放して、次の画像バッチを処理します。

  2. ジェネレーターを使用する: Python のジェネレーターを使用して、すべての画像を一度にメモリーにロードするのではなく、画像を 1 つずつロードします。これによりメモリ使用量が削減され、必要な場合にのみ画像が読み込まれます。

  3. 画像を圧縮する:可能であれば、適切な画像圧縮アルゴリズムを使用して画像を圧縮します。これにより、メモリ内で画像が占有するスペースを削減できます。

  4. リソースを解放する:各画像を処理した後、ファイル ハンドルを閉じるなど、必要がなくなったリソースを時間内に必ず解放してください。

  5. 並列処理:処理を並列で実行できる場合は、処理を高速化し、個々の処理タスクのメモリ使用量を削減するために並列処理の使用を検討してください。

  6. プロフェッショナルな画像処理ライブラリを使用する:画像を 1 つずつストリーミングまたはロードすることをサポートする画像処理ライブラリを使用する場合は、これらの機能を使用してメモリ使用量を削減するようにしてください。

  7. 画像の解像度を下げる:画像の解像度がそれほど重要でない場合は、画像の解像度を下げてメモリ使用量を減らすことができます。

特定のニーズと使用する画像処理ライブラリに応じて、メモリ使用量を削減する適切な方法を選択してください。同時に、各画像の処理後に不要になったリソースを時間内に解放するようにしてください。これにより、メモリ使用量を効果的に削減できます。

3. バッチ処理Pythonサンプルコード

from PIL import Image

def process_images_batch(image_paths, batch_size):
    for i in range(0, len(image_paths), batch_size):
        batch_paths = image_paths[i:i+batch_size]
        batch_images = []

        for path in batch_paths:
            image = Image.open(path)
            # 在这里添加你的图片处理代码
            # 例如:调整图片大小、压缩图片、转换图片格式等
            batch_images.append(image)

        # 在这里添加你的批量处理代码
        # 例如:对每一批图片进行统一处理

        # 在处理完一批图片后,释放内存
        for image in batch_images:
            image.close()

# 示例使用
# 假设你有一个存放图片路径的列表 image_paths
image_paths = ["image1.jpg", "image2.jpg", "image3.jpg", ...]
batch_size = 10  # 每批处理的图片数量

process_images_batch(image_paths, batch_size)

上記のコードは画像をバッチで処理し、画像の各バッチを処理した後にメモリを解放することで、メモリがいっぱいになる問題を回避します。この関数ではprocess_images_batch、画像のサイズ変更、画像の圧縮、画像形式の変換など、必要な画像処理コードを追加できます。

特定のニーズに応じてコードを変更し、batch_size画像の数とメモリの制約に応じて の値を調整してください。こうすることで、大量の画像を効率的に処理できます。過剰なメモリ消費を避けるために、実際の状況に応じてバッチ サイズを合理的に調整してください。

4 番目に、ジェネレーター Python コード例を使用します。

ジェネレーターの使用は、特に大量のデータを扱う場合にメモリを最適化する効果的な方法です。ジェネレーターは、すべてのデータを一度にメモリーにロードせずに、データを 1 つずつ生成できる特別な種類のイテレーターです。これにより、特に大規模なデータセットまたは多数のファイルを処理する場合に、メモリ使用量を大幅に削減できます。

def read_lines(filename):
    with open(filename, 'r') as file:
        for line in file:
            yield line.strip()

def process_data(data):
    # 在这里添加你的数据处理代码
    # 例如:处理每一行数据并返回处理结果
    return processed_data

filename = "large_data.txt"

# 使用生成器逐行读取文件数据
data_generator = read_lines(filename)

# 处理每一行数据
for line in data_generator:
    processed_data = process_data(line)
    # 在这里继续对处理后的数据进行操作,比如输出、保存等
    print(processed_data)

上記の例では、read_lines関数は、指定されたファイルの内容を 1 行ずつ読み取り、各行のデータを返すジェネレーターです。次に、forループを使用してデータを 1 つずつ処理します。これにより、データが処理されるときに、ファイル全体を一度にメモリにロードするのではなく、1 行のデータのみがメモリに格納されます。

ジェネレーターを使用してメモリを最適化する鍵は、一度に大量のデータをメモリにロードしないように、データをバッチで処理し、結果を 1 つずつ生成することです。このアプローチは、大量のデータを処理する場合に非常に効率的であり、メモリ フットプリントを大幅に削減できます。

ジェネレーターはファイル処理で使用するだけでなく、データベース クエリやネットワーク要求応答処理など、大量のデータを処理する必要がある他のシナリオでも使用できます。

実際の状況に応じてジェネレーターの設計を最適化し、データのバッチ処理と結果の生成のロジックを合理的に処理して、最適なメモリ使用量を実現することを忘れないでください。

5、ジェネレータとバッチ処理画像のPythonサンプルコードを組み合わせる

from PIL import Image
import os

def image_generator(image_folder):
    for filename in os.listdir(image_folder):
        image_path = os.path.join(image_folder, filename)
        if os.path.isfile(image_path):
            yield image_path

def process_image_batch(image_paths, batch_size):
    batch_images = []
    for image_path in image_paths:
        with Image.open(image_path) as image:
            # 在这里添加你的图片处理代码
            # 例如:调整图片大小、压缩图片、转换图片格式等
            # 假设处理后返回处理后的图片对象
            processed_image = process_image(image)
            batch_images.append(processed_image)

        if len(batch_images) == batch_size:
            # 在这里添加你的批量处理代码
            # 例如:对每一批图片进行统一处理
            # 假设处理后返回处理后的图片列表
            processed_batch = process_batch(batch_images)
            for processed_image in processed_batch:
                yield processed_image
            batch_images = []

    # 处理剩余不足一批的图片
    if batch_images:
        processed_batch = process_batch(batch_images)
        for processed_image in processed_batch:
            yield processed_image

def process_image(image):
    # 在这里添加你的图片处理代码
    # 例如:调整图片大小、压缩图片、转换图片格式等
    return processed_image

def process_batch(batch_images):
    # 在这里添加你的批量处理代码
    # 例如:对每一批图片进行统一处理
    return processed_batch

image_folder = "images_directory"
batch_size = 10  # 每批处理的图片数量

# 使用图片生成器逐个加载图片
image_gen = image_generator(image_folder)

# 分批处理图片
for batch_images in process_image_batch(image_gen, batch_size):
    # 在这里继续对处理后的图片进行操作,比如保存、展示等
    for image in batch_images:
        image.show()

上記の例では、image_generator関数は指定されたフォルダー内の画像パスを 1 つずつ読み込み、各画像のパスを返すジェネレーターです。process_image_batch関数は画像をバッチで処理する関数で、画像を1つずつ読み込み、バッチサイズに達したときに処理します。処理された画像のバッチが 1 つずつ生成されるため、メモリの使用量が最小限に抑えられます。

ジェネレーターとバッチ処理を組み合わせて使用​​し、特定のニーズと画像処理ロジックに応じてメモリ使用量を最適化し、大量の画像を効率的に処理してください。過剰なメモリ消費を避けるために、実際の状況に応じてバッチ サイズを合理的に調整することを忘れないでください。

おすすめ

転載: blog.csdn.net/xun527/article/details/132087128