Mugichoko's blog

Mugichoko’s blog

しがない研究者のプログラミングを中心としたメモ書き.

画像評価指標のLPIPSを使ってみる

Learned Perceptual Image Patch Similarity (LPIPS)を使ってみた.環境を用意するのが面倒なのでGoogle Colabを使う.基本的には公式のGitのREADME.mdのやり方に沿うだけだが,日本語の記事もあまり見ないので,備忘も兼ねて残すことにする.

実装

lpipsをインストール

pipでインストールできる.

【追記】最近はconda forgeにもある様子conda install -c conda-forge lpips

# https://libraries.io/pypi/lpips
# https://github.com/richzhang/PerceptualSimilarity
# This implementation is form the author of the original paper, Richard Zhang
pip install lpips==0.1.3

以下の様にGoogle Colabの環境下にインストールされる.

Collecting lpips==0.1.3
  Downloading https://files.pythonhosted.org/packages/21/de/774d9cdb601bb938b6a501f1aeaa64288a763ebbafbeef227a3da86150d9/lpips-0.1.3-py3-none-any.whl (53kB)
     |████████████████████████████████| 61kB 2.7MB/s 
Installing collected packages: lpips
Successfully installed lpips-0.1.3

Google Driveのフォルダを準備

root_pathは自分に合ったものに変更.

from google.colab import drive
drive.mount('/content/gdrive')
root_path = 'gdrive/My Drive/Colab Notebooks/LPIPS/'

表示されるリンクに移動して自分のGoogleアカウントでログインし,データの読み書きを許可する.コードが表示されるのでそれを入力ボックス(以下でいう白塗り箇所)にコピペしてエンターを押す.この一連の作業で,Google Driveがマウントされる(アクセスできるようになる).

Go to this URL in a browser: https:xxxx
Enter your authorization code:
████████████████████████████████████████

mounted at /content/gdrive

lpipsをimport

import lpips
loss_fn_alex = lpips.LPIPS(net='alex') # best forward scores
#loss_fn_vgg = lpips.LPIPS(net='vgg') # closer to "traditional" perceptual loss, when used for optimization

モデルが勝手にロードされる.

Setting up [LPIPS] perceptual loss: trunk [alex], v[0.1], spatial [off]
Loading model from: /usr/local/lib/python3.6/dist-packages/lpips/weights/v0.1/alex.pth

LPIPSの値を計算

画像を読み込み,[-1, +1]に値をスケーリングしたものをLPIPSの計算に用いる必要がある.

import torch
import torchvision.transforms.functional as TF
from PIL import Image

path_img0 = root_path + "img0.png"
path_img1 = root_path + "img1.png"

# Variables im0, im1 is a PyTorch Tensor/Variable with shape Nx3xHxW
# (N patches of size HxW, RGB images scaled in [-1,+1])
img0 = Image.open(path_img0)
img0 = (TF.to_tensor(img0) - 0.5) * 2
img0.unsqueeze(0)
#
img1 = Image.open(path_img1)
img1 = (TF.to_tensor(img1) - 0.5) * 2
img1.unsqueeze(0)

# Higher means further/more different. Lower means more similar.
d = loss_fn_alex(img0, img1)
print("Perceptual loss",d)

以下の数値がLPIPSのいわゆるPerceptual Lossらしい.

Perceptual loss tensor([[[[0.1080]]]], grad_fn=<AddBackward0>)

色々な画像で試してみた

せっかくなので色々な画像に対してLPIPSを計算してみた.

画像 適用した処理
元画像 未加工
線を追加 赤い線を手書きで追加
スケーリング バイリニア補間で1/2にダウンスケールした後,2倍にアップスケール
シフト 右下に5画素ずつ移動
グロー Paint.netのEffects/Photo/Glowを適用
ブラー Paint.netのEffects/Blurs/Fragmentを適用
回転 時計回りに回転

f:id:Mugichoko:20201006031604j:plain
元画像と加工画像一覧.カッコ内の値はLPIPSの値.

ボケや回転はその量によってどれくらい値が変化するかは気になるところ(今回はやらない).