MENU

【Python】無料だけど有料級!AI「DPIR」による写真/画像ノイズの除去方法を解説

これまで、SCUNET(Swin-Conv-UNet)やNAFNET(Nonlinear Activation-Free Network)を活用したノイズ除去について紹介してきました。SCUNETはSwin Transformer畳み込みネットワークを組み合わせることで、広範囲の情報を捉えながら高精度なノイズ除去を実現するのが特徴です。一方、NAFNETは非線形活性化関数を排除することで、計算効率を向上させつつ、画像のディテールを保持しながらノイズを除去できるモデルです。

今回は、3つ目の方法として、DPIR(Deep Plug-and-Play Image Restoration)を紹介します。DPIRは、事前学習された深層学習モデルを活用し、プラグアンドプレイ方式でノイズ除去を行うのが特徴です。SCUNETやNAFNETが特定のネットワーク構造を用いてノイズ除去を行うのに対し、DPIRはより汎用的なフレームワークとして機能し、さまざまなノイズタイプに対応できる柔軟性を持っています。

更にDPIRは、ノイズ除去だけではなく、ブレ補正と高解像化の機能が盛り込まれています。DPIRを使ってどこまでノイズを除去できるのか、ブレ補正や高解像化はどこまで実用性があるのか、それを知りたい方は、是非この記事をご覧ください。

目次

DPIRとは

DPIR(Deep Plug-and-Play Image Restoration)は、深層学習を活用した高度な画像復元技術であり、画像の品質を向上させるためのさまざまな機能を備えています。従来の画像復元手法では、特定のタスクごとに個別のモデルを設計・学習する必要がありましたが、DPIRはプラグアンドプレイのアプローチ(事前学習済みのノイズ除去モデルを活用し、ブレ補正や高解像化などの異なる画像復元タスクに適応できる手法)を採用することで、柔軟かつ効率的な復元を可能にしています。

DPIRの特徴は次の通りです。

  • ノイズ除去(Denoising)
    深層学習を活用したノイズリダクション技術により、画像の品質を向上させます。
    特に、ガウスノイズやJPEG圧縮ノイズの除去に優れています。
  • ブレ補正(Deblurring)
    画像のぼやけを軽減し、シャープな視覚効果を実現します。
    モーションブラーやフォーカスブラーの補正に対応。
  • 高解像化(Super-Resolution)
    低解像度の画像を高解像度に変換し、細部のディテールを復元します。
    CNNベースの手法を活用し、従来の超解像技術よりも高精度な結果を提供。
  • デモザイク処理(Demosaicing)
    RAW画像のカラーフィルターアレイ(CFA)から高品質なカラー画像を生成します。
    色の再現性を向上させ、より自然な画像を生成。

参考までに、DPIR、NAFNET、SCUNETの違いをまとめておきます。

モデル特徴メリット適用範囲
DPIR (Deep Plug-and-Play Image Restoration)事前学習モデルを活用し、プラグアンドプレイ方式でノイズ除去汎用性が高く、様々なノイズタイプに対応可能画像復元、医療画像、衛星写真など多用途
NAFNET (Nonlinear Activation-Free Network)非線形活性化関数を排除し、計算効率を向上高速処理が可能で、ディテールを維持しながらノイズを除去低リソース環境、高速処理が求められる場面
SCUNET (Swin-Conv-UNet)Swin Transformerと畳み込みネットワークを組み合わせた構造広範囲の情報を捉えながら高精度なノイズ除去高解像度画像、芸術・写真編集用途

NAFNETは低リソース環境に適していると記載されていますが、DPIR、SCUNETでは問題なく扱える1000万画素越えの画像がNAFNETではメモリ不足に陥ります。
理由は、NAFNETは軽量なネットワーク構造ではありますが、データ量が増えることで、ディテール保持とノイズ除去のバランスを取るための演算量が増え、結果的にメモリが大量に消費されるためです。
一方、DPIR、SCUNETは後発の技術であり、高解像度画像を扱うための設計がされているため、より大きな画像でも処理可能となっています。

DPIRの公式サイト

引用元:DRIR公式GitHub

DPIRの概要とソースコードは、Git上にある DPIR公式ページに掲載されています。本記事では、ここに記載されいている内容をできるだけわかりやすく解説したものになります。

https://github.com/cszn/DPIR/tree/master?tab=readme-ov-file

インストールの前提条件

DPIRのページでは、モデルのダウンロード方法とデモプログラムの使い方に関する記述があるだけで、詳しいインストール方法が記載されていません。

今回は、私のPCで試して動作した構成を記載しています。

Python/CUDAのバージョン

動作に必要な環境は次の通りです。

必要な環境・ライブラリバージョンなど備考
Python 環境Python 3.12.33.10.9でも動作しました
Git 環境その時の最新版
Pytorchtorch 2.0.1+cu118
CUDA Toolkit11.8CPUで動かすならインストール不要
cuDNN8.9.78.9.0以上なら動作可能

インストール手順の概要

次の手順でインストールを行います。

Step1
Python動作環境の構築
①Python 3.12.3の環境準備
②Gitの環境準備
③CUDA Toolkit 11.8のインストール(GPUを使う場合)
④cuDNN 8.9.7
Step2
DPIRのインストール
GitHubからDPIRをインストール後、各種モジュールをインストール
Step3
各種モデルのインストール
GitHubに公開されている学習済みモデルをダウンロードします。
これは、コマンドを1行実行することで完了します。

インストール手順

Step1.Python動作環境の構築

【最初の一歩】生成AI向けPython環境構築手順(スクリーンショットで解説)」の記載内容(①②③、⑤⑥)を実行してください。

Python環境構築手順の①~④をインストールしてください。
FFMPEGのインストールは不要です(使わないだけなので、インストールしても差し支えはありません)。

Step2.DPIRのインストール

あらかじめ、DPIRをインストールするための任意のフォルダを作成しておきます。今回は、Oドライブの直下に DeNiseというフォルダを作成し、そこにインストールすることにします。

まず、コマンドプロンプトを開き、インストールしたいフォルダ(今回はOドライブ直下のDPIRフォルダ)に移動し、次のコマンドを実行します。

git clone https://github.com/cszn/DPIR.git

DPIRのモジュールがインストールに成功したら、次のコマンドを実行してください。

cd dpir
pip install requests
pip install matplotlib
pip install numpy==1.24.3
pip install opencv-python
pip install hdf5storage
pip install scipy

次に、Pytorch をインストールします。GPUを使うか使わないかでコマンドが変わってきます。
お使いのPCに、NVIDIAのGPUが搭載されている場合は、下記のコマンドを実行してください。

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118

CPUのみで動作させたい場合は、下記のコマンドを実行してください。

pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu

NVIDIA RTX-4070 を使う場合、20秒程度で処理できますが、CPUだけで処理させる場合は、Core-i5 13400 のCPUスペックでも1画像に9分程度の処理時間が必要です。

Step3.各種モデルのインストール

続けて、次のコマンドを実行します。これで、必要なモデルが自動的にダウンロードされます。

python main_download_pretrained_models.py --models "DPIR IRCNN" --model_dir "model_zoo"

以上でモデルのインストールは完了です。

DPIRフォルダ構成について

上図は、インストール後のフォルダ構成です。results フォルダは見当たらないかもしれませんが、プログラムを実行した時点で自動的に作成されるので気にしないでください。

ダウンロードしたモデルファイルは、model_zoo フォルダに格納されています。
testsets フォルダにはテスト用のサンプル画像が置かれていますが、ブレ補正のデモ画像以外は自力で入手が必要です。results フォルダには、処理結果の画像が格納されます。

デモプログラムとして、8個のPythonプログラムが置かれています。それぞれの概要は次の通りです。

ファイル名説明
main_download_pretrained_models.py事前学習済みモデルをダウンロードするためのスクリプト
main_dpir_deblocking_color.pyカラー画像のブロックノイズを除去するためのスクリプト
main_dpir_deblocking_grayscale.pyグレースケール画像のブロックノイズを除去するためのスクリプト
main_dpir_deblur.py画像のぼかしを除去するためのスクリプト
main_dpir_demosaick.pyデモザイク処理を行うためのスクリプト
main_dpir_denoising.py画像のノイズを除去するためのスクリプト
main_dpir_sisr.py単一画像超解像(SISR)を行うためのスクリプト
main_dpir_sisr_real_applications.py実際のアプリケーションで単一画像超解像を行うためのスクリプト

見ての通り、ノイズ除去・ブレ補正・超解像などの機能が確認できるようになっています。

DPIRデモプログラムの起動方法

コマンドプロンプトを開き、DPIRをインストールしたフォルダの直下に移動したあとで、デモプログラムを実行します。

カラーノイズの除去

まず最初に、カラーノイズを除去してみます。カラーノイズ除去は main_test_scunet_color_gaussian.py を使います。

python main_dpir_denoising.py

残念ながら、このデモプログラムは、起動時の引数としてパラメータ(モデル名、入力フォルダ、出力フォルダなどの指定)を受け取ることが出来ません。従って、ソースコードを直接書き換える必要があります。

エディタでプログラムに記載されているパラメータを変更する

まずテキストエディタで、python main_dpir_denoising.py を開いて、赤枠の部分を書き換えて下さい。

以下は、ノイズ除去において特に変更が必要となる部分のみを抜き出し、テーブルにまとめたものです。

パラメータ名初期値説明
noise_level_img15画像に含まれるノイズの量(レベル)を指定します。
ノイズ除去の強さを指定する訳ではないことに注意して下さい。
目安は次の通りです。
・ほとんどノイズが無い状態(高画質な画像):5~10
・標準的なノイズ(スマホや一般的なデジカメ画像):15~25
・中程度のノイズ(夜景や低光環境での高感度撮影):30~50
・極端なノイズ(極端に暗い場所での高感度撮影):50以上
model_name'drunet_gray'白黒画像の場合:'drunet_gray'
カラー画像の場合: 'drunet_color'
testset_name'bsd68'ノイズ除去対象の画像を保存してあるフォルダ名。
testsetsフォルダの直下に作る必要がある。
x8Falseオリジナル画像に回転や反転を加えて8種類の画像を生成し、それを元にノイズ除去を行う。品質は向上するが、処理が重くなる。
testsets'testsets'testset_nameで指定したフォルダの親フォルダ。
任意のフォルダに書き換えると、その場所にtestset_nameで指定したフォルダが作成される。
results'results'処理結果の出力フォルダ。このフォルダ直下に、testset_nameで指定したフォルダに対応するフォルダが作成され、そこに結果が出力される。

今回は、Fimi Palm 2 Pro という小型のジンバルカメラで撮影したISO感度1600の写真を使って検証します。
スマートフォンと同じくらい小さな受光センサーなので、かなりの量のノイズが載っています。
(1回クリックすると拡大し、もう1度クリックすると等倍表示されます)


こちらのリンクを右クリックし、「名前を付けてリンク先を保存」を選択すると、上記のテスト画像(4000×2252)がダウンロードできます。

かなりノイズ量が多いので、ノイズレベルを50としました。ダウンロードした画像は、testsets フォルダ配下に test フォルダを作成し、そこに格納しておきます。

従って、python main_dpir_denoising.py の53行目~56行目までの4行を、下記の内容に書き換えて保存してください。(3行目は変更不要なので、もとのコードのままです)

    noise_level_img = 50                 # set AWGN noise level for noisy image
    noise_level_model = noise_level_img  # set noise level for model
    model_name = 'drunet_color'          # set denoiser model, 'drunet_gray' | 'drunet_color'
    testset_name = 'test'                # set test set,  'bsd68' | 'cbsd68' | 'set12'

ノイズ除去したい画像を配置する

画像をダウンロードしたら、resuls フォルダ直下に test フォルダを作成し、そこにテスト画像をコピーしてください。

main_dpir_denoising.py を実行する

下記のコマンドを実行します。

python main_dpir_denoising.py

ノイズ除去後の画像を取得する

結果は、resultsフォルダ直下に、「testset_name で指定したフォルダ」+「model_name で指定したモデル名」でフォルダが作成され、そこにノイズ除去画像が格納されます。

見違えるようにノイズが除去されていることが分かります。感動ですね!

入力画像

出力画像

ノイズレベル(noise_level_img)の値でノイズ除去画質はどう変わるか?

noize_level_img について、 25,50,70,100,150 それぞれの値で画質を検証しました。

noize_level_img は、「画像に含まれるノイズの強さ(量)」をモデルに伝えるためのもので、画像に含まれるノイズの推定値として使用されます。モデルはこの値に基づいてノイズ除去を行うため、実際のノイズ量に近い値を指定することが理想的です。

とはいうものの、画像を目視で確認して正確なノイズ量を判断するのは困難であり、検証を繰り返して「最適な落としどころ」を見つける作業が必要になります。

このプロセスが、実質的に「ノイズ除去の強さを調整する作業」と近い感覚になるため、ノイズ除去の強さを調整すると考えても良いかもしれません。ノイズが過剰に除去されてディテールが失われる、または除去が不十分でノイズが残る場合、この値を調整することでバランスを取ることになります。

掲載している画像は、1回クリックすると拡大され、更にクリックすると等倍表示されるので、ノイズ除去量やディテールの状態については、画像を拡大してご確認ください。


オリジナル画像

noise_level_img:25

noise_level_img:50

noise_level_img:70

noise_level_img:100

noise_level_img:150

main_dpir_denoising.py にパラメータを引数で渡せるようにする

パラメータを変更するたび、毎回ソースコードを変更するのは使い勝手が悪いので、少しだけソースコードを変更しておきます。
変更をミスするとエラーになるので、main_dpir_denoising.pymain_dpir_denoising2.py という名前でコピーして、そちらを変更するようにします。

12行目に下記のソースコードを挿入します。

import argparse

# 引数の定義
parser = argparse.ArgumentParser()
parser.add_argument('--noise_level_img', type=int, default=50, help='AWGN noise level for the noisy image')
parser.add_argument('--model_name', type=str, default='drunet_color', help='Model name: drunet_gray | drunet_color')
parser.add_argument('--testset_name', type=str, default='test', help='Testset name: bsd68 | cbsd68 | set12 | test')
parser.add_argument('--x8', action='store_true', help='Set x8 augmentation')
parser.add_argument('--testsets', type=str, default='testsets', help='Path to testsets folder')
parser.add_argument('--results', type=str, default='results', help='Path to results folder')
args = parser.parse_args()

53行目~74行目のソースコードを、下記の内容に置き換えます(実際には、ハイライト行だけ置き換えれば問題ありません)。

    noise_level_img = args.noise_level_img
    noise_level_model = noise_level_img
    model_name = args.model_name
    testset_name = args.testset_name
    x8 = args.x8
    show_img = False
    border = 0

    if 'color' in model_name:
        n_channels = 3
    else:
        n_channels = 1

    model_pool = 'model_zoo'             # fixed
    testsets = args.testsets             # ←引数から
    results = args.results               # ←引数から
    task_current = 'dn'
    result_name = testset_name + '_' + task_current + '_' + model_name

    model_path = os.path.join(model_pool, model_name+'.pth')
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    torch.cuda.empty_cache()

これで、下記の引数が使えるようになります。

引数名初期値説明
--noise_level_imgint50入力画像に加えるAWGN(加法性ホワイトガウス雑音)のノイズレベル
--model_namestrdrunet_color使用するモデル名。drunet_gray または drunet_color を指定
--testset_namestrtestテストセット名。bsd68 / cbsd68 / set12 / test のいずれかを指定
--x8boolFalsex8データ拡張を有効にするか。指定があると有効
--testsetsstrtestsetsテストセットフォルダへのパス
--resultsstrresults結果を保存するフォルダへのパス

使用例は次の通りです。

python main_dpir_denoising.py --model_name drunet_color --noise_level_img=50 --testsets test

まとめ

今回は DPIR(Deep Plug-and-Play Image Restoration) について、インストール方法と使い方を紹介しました。

DPIR によるノイズ除去は非常に強力で、劇的に綺麗になります。有料サービスのノイズ除去にも負けない実力です。

ただし、CPUだけでノイズ除去することも可能ですが、1000万画素の画像1枚当たり10分(Core-i5 13400使用時)くらい処理時間必要となるため、本格的に使うにはGPUが不可欠です。

幸いにも、フォルダに複数のファイルをコピーしておけば、あとは放置でノイズ除去してくれるので、パソコンの空き時間を活用すれば安価にノイズ除去が実現できます。

ノイズ除去で悩んでいる方は、是非一度お試しください。

この記事が気に入ったら
いいねしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次