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 を適用 |
回転 | 時計回りに回転 |
ボケや回転はその量によってどれくらい値が変化するかは気になるところ(今回はやらない).