はじめに (対象読者・この記事でわかること)

この記事は、Pythonで画像処理を行っている方、特に画像を保存する際に予期せぬノイズが発生してしまい、その原因が分からず困っている方を対象としています。画像生成AIの出力画像を保存する際や、取得した画像を加工して保存する際などに、このノイズ問題に直面することがあります。

この記事を読むことで、Pythonで画像保存時にノイズが発生する主な原因を理解し、Pillow (PIL) や OpenCV といった一般的な画像処理ライブラリを用いた具体的なノイズ除去・抑制方法を習得できます。さらに、ノイズ発生を防ぐための画像保存時の設定についても解説します。

前提知識

この記事を読み進める上で、以下の知識があるとスムーズです。 * Pythonの基本的な文法 * 画像処理ライブラリ Pillow (PIL) または OpenCV の基本的な使い方

画像保存時にノイズが発生する原因を探る

Pythonで画像を扱う際、特にPNGやJPEGといった圧縮形式で保存する際に、意図しないノイズが発生することがあります。このノイズは、単なる表示上の問題ではなく、保存された画像ファイル自体に記録されている場合が多いです。原因は多岐にわたりますが、大きく分けて以下の3つが考えられます。

1. 画像フォーマットの圧縮特性による劣化

JPEGのような非可逆圧縮フォーマットは、ファイルサイズを小さくするために、人間の目には感知しにくい情報を削減します。しかし、この圧縮プロセスが、特に細かいディテールや色のグラデーション部分に「圧縮アーティファクト」と呼ばれるブロックノイズやリンギング(輪郭のギザギザ)といった形で現れることがあります。PNGは可逆圧縮ですが、それでも保存時の設定や、元画像の複雑さによっては、わずかな劣化が見られる可能性はゼロではありません。

2. 画像データの色深度やカラープロファイルの問題

画像データの色深度が低い場合(例えば、8ビットカラー)、色の階調が少なくなり、滑らかなグラデーションが「バンディング(帯状のノイズ)」として現れることがあります。また、画像に埋め込まれているカラープロファイル(ICCプロファイルなど)が、表示環境と一致しない場合、色の再現性が損なわれ、意図しない色味やノイズのように見える現象が発生することもあります。

3. ライブラリの実装や設定の不備

使用している画像処理ライブラリ(PillowやOpenCVなど)の特定のバージョンにおけるバグ、あるいは保存時のパラメータ設定の不備によってもノイズが発生することがあります。例えば、JPEGの品質設定が低すぎたり、PNGの圧縮レベルが不適切だったりすると、期待通りの画像が得られないことがあります。

Pythonにおけるノイズ対策と具体的な実装例

ここでは、前述の原因を踏まえ、PillowとOpenCVを使った具体的なノイズ対策方法を解説します。

1. Pillow (PIL) を使用したノイズ対策

PillowはPythonで最も広く使われている画像処理ライブラリの一つです。

1.1. JPEG保存時の品質設定の調整

JPEG保存時のノイズは、主に圧縮品質が原因です。Image.save()メソッドのqualityパラメータを調整することで、ノイズの発生を抑制できます。qualityは0から95の範囲で指定し、値が大きいほど高品質(ファイルサイズ大)になります。一般的には85〜90程度が推奨されます。

Python
from PIL import Image # 画像を開く img = Image.open("input_image.jpg") # 高品質でJPEG保存 (qualityを90に設定) img.save("output_image_high_quality.jpg", quality=90) # 標準的な品質でJPEG保存 (qualityを80に設定) img.save("output_image_standard_quality.jpg", quality=80)

1.2. PNG保存時の圧縮レベルとフィルタリング

PNGは可逆圧縮ですが、保存時の圧縮レベルやフィルタリング設定も画質に影響を与えることがあります。compress_levelは0(圧縮なし)から9(高圧縮)まで、optimizeはTrueで最適化を試みます。

Python
from PIL import Image img = Image.open("input_image.png") # 高圧縮・最適化を試みてPNG保存 img.save("output_image_optimized.png", compress_level=9, optimize=True) # 圧縮レベルを低くしてPNG保存 (ファイルサイズは大きくなるが、処理速度は速い場合も) img.save("output_image_low_compress.png", compress_level=1)

1.3. 色深度の確認と変換

必要に応じて、画像の色深度を確認し、必要であればより広い色空間に変換してから保存することも検討できます。例えば、img.modeで色モードを確認できます。

2. OpenCV を使用したノイズ対策

OpenCV (cv2) は、より高度な画像処理やリアルタイム処理に特化したライブラリです。

2.1. JPEG保存時の品質指定

OpenCVでも、cv2.imwrite()関数でJPEG保存時の品質を指定できます。params引数にcv2.IMWRITE_JPEG_QUALITYを指定します。

Python
import cv2 # 画像を読み込む (BGR形式) img = cv2.imread("input_image.jpg") # 高品質でJPEG保存 (qualityを90に設定) cv2.imwrite("output_image_cv_high_quality.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 90]) # 低品質でJPEG保存 (qualityを50に設定) cv2.imwrite("output_image_cv_low_quality.jpg", img, [cv2.IMWRITE_JPEG_QUALITY, 50])

2.2. PNG保存時の圧縮レベル指定

PNG保存時も、cv2.IMWRITE_PNG_COMPRESSIONで圧縮レベルを指定できます。値は0(圧縮なし)から9(高圧縮)までです。

Python
import cv2 img = cv2.imread("input_image.png") # 高圧縮でPNG保存 cv2.imwrite("output_image_cv_high_compress.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 9]) # 圧縮レベルを低くしてPNG保存 cv2.imwrite("output_image_cv_low_compress.png", img, [cv2.IMWRITE_PNG_COMPRESSION, 1])

2.3. ノイズ除去アルゴリズムの適用(保存前処理)

もし、元画像自体にノイズが含まれている場合、保存前にノイズ除去アルゴリズムを適用することが最も効果的です。OpenCVには、様々なノイズ除去関数が用意されています。

  • ガウシアン平滑化 (cv2.GaussianBlur): 比較的緩やかなノイズ除去。
  • メディアンフィルタ (cv2.medianBlur): 塩害ノイズ(サルテノイズ)に有効。
  • 非局所平均フィルタ (cv2.fastNlMeansDenoisingColored): より高度で、カラー画像の詳細を保持しながらノイズを除去するのに優れています。

ここでは、fastNlMeansDenoisingColoredを使った例を示します。

Python
import cv2 import numpy as np # 画像を読み込む (BGR形式) img = cv2.imread("noisy_image.jpg") # ノイズ除去パラメータ (これらの値は画像によって調整が必要) # h: ノイズ除去の強さ (大きいほど強く除去) # hForColorComponents: カラー画像の場合のパラメータ # templateWindowSize: ノイズ除去のために比較するパッチのサイズ # searchWindowSize: ノイズ除去のために探索する領域のサイズ h = 10 hForColorComponents = 10 templateWindowSize = 7 searchWindowSize = 21 # カラー画像用のノイズ除去を実行 denoised_img = cv2.fastNlMeansDenoisingColored(img, None, h, hForColorComponents, templateWindowSize, searchWindowSize) # ノイズ除去された画像を保存 cv2.imwrite("denoised_and_saved_image.jpg", denoised_img, [cv2.IMWRITE_JPEG_QUALITY, 90]) print("ノイズ除去と保存が完了しました。")

このノイズ除去アルゴリズムは、パラメータの調整が重要です。h, hForColorComponents, templateWindowSize, searchWindowSizeといったパラメータを、対象の画像に合わせて試行錯誤する必要があります。一般的には、hhForColorComponentsを大きめに設定すると、より強力にノイズが除去されますが、画像の詳細が失われやすくなります。

2.4. 画像フォーマットの選択

ノイズを極力避けたい場合は、JPEGではなくPNG形式で保存することを強く推奨します。PNGは可逆圧縮であるため、圧縮による画質劣化がありません。

3. その他の考慮事項

  • 元画像の解像度: 元画像の解像度が低い場合、拡大するとノイズが目立ちやすくなります。
  • 画像生成AIの出力: AI生成画像の場合、生成時の設定やモデルの特性によってノイズが発生しやすいため、生成時のパラメータ調整が重要です。

まとめ

本記事では、Pythonで画像保存時に発生するノイズ問題について、その原因と具体的な解決策を解説しました。

  • ノイズの主な原因は、JPEGのような圧縮フォーマットの特性、色深度やカラープロファイルの問題、ライブラリの設定不備などにあります。
  • Pillowでは、qualityパラメータを高く設定したり、PNGのcompress_leveloptimizeを調整することでノイズを抑制できます。
  • OpenCVでも同様に、cv2.IMWRITE_JPEG_QUALITYcv2.IMWRITE_PNG_COMPRESSIONで保存品質を調整できます。
  • 元画像にノイズがある場合は、保存前にOpenCVのノイズ除去アルゴリズム(例: cv2.fastNlMeansDenoisingColored)を適用するのが効果的です。
  • ノイズを極力避けたい場合は、PNG形式での保存を推奨します。

これらの対策を講じることで、Pythonでの画像保存におけるノイズ発生を大幅に軽減し、より高品質な画像を扱うことができるようになります。

参考資料