こしあん
2019-07-20

画像のダウンサンプリングとPSNRの測定

Pocket
LINEで送る


U-Netでどこまでの深さが効いているのかを考えるために、画像をダウンサンプリングし、アップサンプリングするという処理を行いPSNRを見ていきます。その結果、PSNRが15~20程度だと、U-Netの深い層が効かないかもしれないという状況を確認することができました。

きかっけ・考え方

U-Netの実装を考えるとき、DecoderにおいてSkip-Connection側の入力が効いているのか、深層側の入力が効いているのかよくわからないことがあります。そこで、どっちが効くかの指標として「画像をある層での解像度にダウンサンプリングしたときに、PSNRで測ってどれぐらいになるか?」を調べるのが有効ではないかと思ったのです。

どういうことかというと、次のような方式です。

  • 画像(例:256×256)をある層の解像度にあうように、ダウンサンプリング(例えば32×32)とする。具体的にはAveragePooling。
  • ダウンサンプリングした画像を元の解像度にアップサンプリング(Nearest Neighbor法)する
  • 当然ダウンサンプリング→アップサンプリングした画像は画質が明らかに悪くなっているので、その画像と元の画像とのPSNRを取る
  • このPSNRを解像度別(32×32, 16×16など)取って比較する

これがなぜU-Netにおいて意味あるかというと、

  • ある解像度において求められたPSNRを$p_i$とする
  • ネットワークの出力でのPSNRを同じく見る
  • 出力のPSNRが$p_i$より低いか同程度なら、$i$に対応する層でより深い層の出力ではなく、Skip-Connection側が効いていると考えられる。なぜなら、より深い層を頑張って訓練するより、Skip-Connectionの入力をコピペしたほうが楽だから。
  • 出力のPSNRが$p_i$より高ければ、$i$に対応する層でより深い層の入力が効いていると考えられる。なぜなら、SkipConnectionの入力をコピペしただけでは、その画質は再現できないから。

したがって、訓練を通さないにしろ、$p_i$がU-Netにおいて深い層が効くか効かないかのある種の目安として扱うことができます。これはSkip-Connection側が効くか、深層側が効くか結果を見てみないとわからないU-Netにおいて結構有効ではないでしょうか。

実験

前処理

KaggleのMyWaifuListデータセットを使います。前処理としてカラー画像のみを抽出しました。カラー画像の抽出は、チャンネル単位でのピクセルの相関係数を取り、その相関行列の平均が0.995より低いものをカラー画像としました。もともと別の訓練の過程で作ったデータなので、その中から2048枚をテスト画像として除外しています。訓練画像12443枚についてPSNRの計算をします。

これらの画像について、256×256にダウンサンプリングします。LANCZOS法によってリサイズします。この画像を真の画像(img_true)とします。

比較実験

真の画像img_trueを以下の解像度にAvg Pooling→Nearest Neighborのアップサンプリングをします。これをPU変換と呼ぶことにします。

  • 128×128 (2倍)
  • 64×64 (4倍)
  • 32×32 (8倍)
  • 16×16 (16倍)
  • 8×8 (32倍)

もとの解像度で割った値をスケール倍率とします。スケール倍率が高いほど画質は落ちます。PU変換後の画質ばスケール倍率が高いほど落ちます。PU変換後の解像度はimg_trueの解像度256×256と一致します。PU変換後の画像に対して$p_i$を計算します。

この説明では、「真の画像img_trueとimg_trueをPU変換した画像のPSNR」を求めましたが、U-Netにおいては入力≠img_trueであることが普通なので、PU変換をする画像に別の前処理を施します。

  1. 真の画像img_trueをグレースケール化する(ただし3チャンネルのまま)。これをimg_grayとする。img_grayに対してPU変換をし、img_trueとのPSNRを取る。これは白黒画像のカラー化でのタスクを想定。
  2. 真の画像img_trueにモザイクをかける。モザイクの掛け方は後述。これをimg_mosaicとする。img_mosaicに対してPU変換をし、img_trueとのPSNRを取る。これはU-Netによるモザイク除去のタスクを想定。

また、モザイクをかける際は次のようにします。

  • img_trueに対して、16倍のスケール倍率でPU変換
  • 半径4ピクセルのガウシアンぼかしを使う

これにより生成されるのがimg_mosaicです。

すべての画像において、PSNRを計算するときは比較対象はimg_trueを対象にします。したがって、img_trueのPU変換よりも、img_gray, img_mosaicのほうがPSNRの値は低くなります。

可視化

img_true、img_gray、img_mosaicのPU変換をスケール倍率ごとに可視化したものがこちらです。上から、「本物、スケール倍率2倍、4倍……」です。

img_true

img_gray

img_mosaic

おおよそイメージがつかめたのではないでしょうか。スケール倍率を上げれば上げるほどモザイクがかかったような出力になります。

結果

画像別の結果を示します。

スケール倍率 img_real img_gray img_mosaic
1 19.85 15.58
2 24.61 18.65 15.58
4 20.77 17.39 15.55
8 18.32 16.19 15.41
16 16.31 14.97 15.17
32 14.57 13.74 14.22

img_realの場合は、8×8解像度まで落とすとPSNRは15を切ることがわかりました。32×32ならPSNRは20を越えないぐらい。訓練の進むとして評価関数にPSNRを使うことはよくあるので、これはわかりやすいです。

img_grayの場合は、img_realのカラー情報を落としているため、PSNRはより低くなります。しかし、低解像度領域においてはそこまでPSNRの差は出ません。スケール倍率が8より大きいと、PSNRでの差は2よりも小さくなります。これは驚きでした。カラー情報がPSNRの決定的な差になるのはスケール倍率が低い、つまり高解像度領域となります。

img_mosaicの場合は、そもそも前処理でPU変換をしているため、PSNRは頭打ち傾向にあります。もちろん、前処理のPU変換が16×16解像度まで落としているので、スケール倍率が16までの差はほぼ誤差のようなものです。32まで倍率を上げると、ガクッとPSNRが落ちます。

考察

U-Netを使った画像変換において、PSNRが15~25ぐらいというのは結構あるケースなのですが、それはもしかするとこれで見たように低解像度のSkip Connectionによるコピーで再現できるかもしれません。したがって、深い層の訓練が進まない可能性は考えられます。どこまでの深さが訓練されるか、あるいは意味あるのかを見るのは、こういった考察をするのが簡単かつ有効かもしれません。

可視化の部分で確認したように、PU変換というのはやっていることはモザイクの付与であるため、モザイクについて考えることがU-Netの挙動を考える際に有効となるやもしれません。一見ふざけているようにみえるモザイクというのは、画像処理の本質的な部分を突いている、と言えるのではないでしょうか。

Related Posts

PyTorchで複数のGPUで訓練するときのSync Batch Normalizationの必要性... PyTorchにはSync Batch Normalizationというレイヤーがありますが、これが通常のBatch Normzalitionと何が違うのか具体例を通じて見ていきます。また、通常のBatch Normは複数GPUでData Parallelするときにデメリットがあるのでそれも確認し...
Kerasで損失関数に複数の変数を渡す方法... Kerasで少し複雑なモデルを訓練させるときに、損失関数にy_true, y_pred以外の値を渡したいときがあります。クラスのインスタンス変数などでキャッシュさせることなく、ダイレクトに損失関数に複数の値を渡す方法を紹介します。 元ネタ:Passing additional arguments...
Google ColabのTPU環境でmodel.fitのhistoryが消える現象... Google ColabのTPU環境でmodel.fitしたときに、通常の環境で得られるhistory(誤差や精度のログ)が消えていることがあります。その対応法を示します。 原因はTPU用のモデルに変換したから まず結論からいうとこの現象はCPU/GPU環境では再発しません。TPU環境特有の現...
PyTorchでConvolutionフィルターをやる(エッジ検出やアンシャープマスク)... PyTorchでPILのConvolutionフィルター(エッジ検出やアンシャープマスク)をやりたくなったので、どう実装するか考えてみました。 やりたいこと PIL/PillowのConvolutionフィルター(ImageFilterなど)の処理をPyTorchの畳み込み演算で再現したい ...
ディープラーニング=最小二乗法のどこがダメなのか解説する... あるニュース記事で、ディープラーニング=最小二乗法で三次関数なんていう「伝説の画像」が出回っていたので、それに対して突っ込みつつ、非線形関数という立場からディープラーニングの本当の表現の豊かさを見ていきたいと思います。 きっかけ ある画像が出回っていた。日経新聞の解説らしい。 伝説の画像にな...
Pocket
Delicious にシェア

Add a Comment

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です