Coder Social home page Coder Social logo

kcui / elpips Goto Github PK

View Code? Open in Web Editor NEW

This project forked from mkettune/elpips

0.0 2.0 0.0 113.71 MB

E-LPIPS: Robust Perceptual Image Similarity via Random Transformation Ensembles

License: BSD 2-Clause "Simplified" License

Python 98.66% Shell 1.34%

elpips's Introduction

E-LPIPS: Robust Perceptual Image Similarity via Random Transformation Ensembles

Python 3.6 TensorFlow 1.12

Teaser image

Figure 1: The neural perceptual image similarity metric LPIPS allows crafting images that look very different from a source image, while staying close to the original in terms of the metric (red). We fortify LPIPS by applying an ensemble of random transformations to the images before measurement: each additional transformation decreases the amount by which the image can be changed while staying at a constant LPIPS distance from the original. Our full E-LPIPS metric (green) retains the predictive power of LPIPS but is much more robust.

This repository contains the implementation of the image similarity metric proposed in the following paper:

E-LPIPS: Robust Perceptual Image Similarity via Random Transformation Ensembles
Markus Kettunen (Aalto University), Erik Härkönen (Aalto University), Jaakko Lehtinen (Aalto University, NVIDIA)
https://arxiv.org/abs/1906.03973

Abstract: It has been recently shown that the hidden variables of convolutional neural net-works make for an efficient perceptual similarity metric that accurately predicts human judgment on relative image similarity assessment. First, we show that such learned perceptual similarity metrics (LPIPS) are susceptible to adversarial attacks that dramatically contradict human visual similarity judgment. While this is not surprising in light of neural networks’ well-known weakness to adversarial perturbations, we proceed to show that self-ensembling with an infinite family of random transformations of the input — a technique known not to render classification networks robust — is enough to turn the metric robust against attack, while retaining predictive power on human judgments. Finally, we study the geometry imposed by our novel self-ensembled metric (E-LPIPS) on the space of natural images. We find evidence of “perceptual convexity” by showing that convex combinations of similar-looking images retain appearance, and that discrete geodesics yield meaningful frame interpolation and texture morphing, all without explicit correspondences.

Acknowledgements

We thank Pauli Kemppinen, Frédo Durand, Miika Aittala, Sylvain Paris, Alexei Efros, Richard Zhang, Taesung Park, Tero Karras, Samuli Laine, Timo Aila, and Antti Tarvainen for in-depth discussions; and Seyoung Park for helping with the TensorFlow port of LPIPS. We acknowledge the computational resources provided by the Aalto Science-IT project.

Resources

All material related to our paper is available via the following links:

Licenses

The code is licensed under a BSD 2-Clause License.
Copyright information for the images in the inputs directory is found in file inputs/LICENSE.

The SqueezeNet and VGG16 implementations use pretrained weights from PyTorch Torchvision.

System requirements

  • Python 3.6
  • TensorFlow 1.12 with GPU support

The environment can be set up with Anaconda by running the following commands:

  1. conda env create -f environment.yml
  2. conda activate elpips

Experiment: Geodesic Interpolation

Figure 2. Geodesic interpolation (shortest path) between two input images, computed in different distance metrics. No optical flow or explicit image warping is performed; the E-LPIPS geodesics' morphing and image transformations emerge purely from the geometry induced by the metric. Please see the paper for details.

Usage

The minimum code to use E-LPIPS is as follows:

import elpips
metric = elpips.Metric(elpips.elpips_vgg(batch_size=1))
tf_distance = metric.forward(tf_image1, tf_image2)
distance = sess.run(tf_distance)

The images need to be NHWC tensors with N = batch_size.

Known issues

  • Code for creating geodesic interpolations not yet released (COMING SOON!)
  • Running elpips with n > 1 (by configuring elpips.elpips_vgg(batch_size, n)) may freeze on some versions of TensorFlow due to tf.while_loop being unstable

Examples

This repository contains scripts that demonstrate various ways to use E-LPIPS:

File Description
ex_simple_distance.py Evaluates the E-LPIPS distance between two images.
ex_evaluate_distance.py Evaluates the E-LPIPS distance of two images with an automatic iteration count.
ex_compare_distances.py Given a reference and two inputs, finds which one is closer.
ex_pairwise_average.py Finds the E-LPIPS average (barycenter) of two images.
ex_bary10.py Finds the E-LPIPS average (barycenter) of ten similarly perturbed versions of an input image.
train_run.py Trains the LPIPS weights for a network. Can be used for both E-LPIPS and LPIPS.
train_test_2afc.py Runs the 2AFC test for a model.

ex_simple_distance.py

A simple piece of code that evaluates the E-LPIPS distance between two images. This is a stochastic evaluation and the result will vary slightly between evaluations. For increased precision use parameter -n=<number> to average over more samples. The default value is 200. This E-LPIPS implementation can also be used to evaluate LPIPS-VGG and LPIPS-SQUEEZENET distances.

Warning: Some versions of TensorFlow may have bugs that freeze the program for n > 1.

Computing E-LPIPS distance
> python ex_simple_distance.py inputs/adv_anchor.png inputs/adv_reference.png
Distance (e-lpips-vgg): 0.015902504324913025

> python ex_simple_distance.py inputs/adv_vgg_sqz.png inputs/adv_reference.png -n=1000
Distance (e-lpips-vgg): 0.08437894284725189
Computing LPIPS-VGG distance
> python ex_simple_distance.py inputs/adv_anchor.png inputs/adv_reference.png --metric=lpips_vgg
Distance (lpips-vgg): 0.025399859994649887

> python ex_simple_distance.py inputs/adv_vgg_sqz.png inputs/adv_reference.png --metric=lpips_vgg
Distance (lpips-vgg): 0.01992170885205269
Computing LPIPS-SQUEEZENET distance
> python ex_simple_distance.py inputs/adv_anchor.png inputs/adv_reference.png --metric=lpips_squeeze
Distance (lpips-squeeze): 0.02187105268239975

> python ex_simple_distance.py inputs/adv_vgg_sqz.png inputs/adv_reference.png --metric=lpips_squeeze
Distance (lpips-squeeze): 0.02113761380314827

ex_evaluate_distance.py

Evaluates the E-LPIPS distance of two images with an automatic iteration count.

Continues sampling until error of mean reaches both '--max_absolute_error' and '--max_relative_error' (with 1.96 sigma bounds), or sample count exceeds '--max_iterations'.

Computing E-LPIPS distance:

> python ex_evaluate_distance.py inputs/adv_anchor.png inputs/adv_reference.png

Evaluating E-LPIPS until abs_error < 0.01 and rel_error < 0.025, but at most 5000 iterations.
   [Processed samples: 50.  Current estimate: 0.02014327932614833 +- 0.002459478428475225 (12.2099%)]
   [Processed samples: 100.  Current estimate: 0.017760459808632733 +- 0.001853305389334146 (10.4350%)]
   ...
   [Processed samples: 2050.  Current estimate: 0.016594534157150675 +- 0.00041920152693091103 (2.5261%)]
   [Processed samples: 2100.  Current estimate: 0.016498371701066692 +- 0.00041416787483436755 (2.5104%)]
Distance (elpips_vgg): 0.01651083237308493
   +- 0.00041136488234548807 or 2.4915%  (bounds: 1.96 σ)

ex_compare_distances.py

A simple piece of code that compares a reference image to two other images and tells which one of them is closer to the reference. The code samples the distances of the two images simultaneously, using the same dropout and random input transformations for both. This makes the error in the distance samples for d1 and d2 correlated so the comparison requires fewer samples.

Comparing which of two images is closer to a reference, using E-LPIPS:
> python ex_compare_distances.py inputs/adv_reference.png inputs/adv_anchor.png inputs/adv_vgg_sqz.png
Image 'inputs/adv_anchor.png' is closer! (*0.01716* - 0.08547 = -0.06831 < 0)
Comparing which of two images is closer to a reference, using LPIPS-VGG:
> python ex_compare_distances.py inputs/adv_reference.png inputs/adv_anchor.png inputs/adv_vgg_sqz.png --metric=lpips_vgg
Image 'inputs/adv_vgg_sqz.png' is closer! (0.02540 - *0.01992* = 0.00548 > 0)
Comparing which of two images is closer to a reference, using LPIPS-SQUEEZENET:
> python ex_compare_distances.py inputs/adv_reference.png inputs/adv_anchor.png inputs/adv_vgg_sqz.png --metric=lpips_squeeze
Image 'inputs/adv_vgg_sqz.png' is closer! (0.02187 - *0.02114* = 0.00073 > 0)

ex_pairwise_average.py

Finds the E-LPIPS average (barycenter) of two images. Starts from random noise and optimizes for the image that minimizes the sum of the squared E-LPIPS distances to the input images.

Outputs are generated by default into directory out_bary2, but this directory may be changed with --outdir. The output directory will contain snapshots of the optimization, which are often quite interesting.

The final result will be outdir/100000.png by default.

Note that this simple algorithm is very slow and may take hours to complete. The results will only be representative near the maximum iteration count.

Finding the E-LPIPS average of two images:
> python ex_pairwise_average.py inputs/cat.png inputs/dog.png --outdir=out_bary2_cat_dog_elpips
Finding the LPIPS-VGG average of two images:
> python ex_pairwise_average.py inputs/cat.png inputs/dog.png --outdir=out_bary2_cat_dog_vgg --metric=lpips_vgg
Finding the LPIPS-SQUEEZENET average of two images:
> python ex_pairwise_average.py inputs/cat.png inputs/dog.png --outdir=out_bary2_cat_dog_vgg --metric=lpips_squeeze

ex_bary10.py

Finds the E-LPIPS average (barycenter) of ten similarly perturbed versions of an input image. Starts from random noise and optimizes for the image that minimizes the sum of the squared E-LPIPS distances to the input images.

Supported perturbations include additive Gaussian noise and small shifts.

Outputs are generated by default into directory out_bary10, but this directory may be changed with --outdir. The output directory will contain snapshots of the optimization, which are often quite interesting.

The final result will be outdir/100000.png by default.

Note that this simple algorithm is very slow and may take hours to complete. The results will only be representative near the maximum iteration count.

Running the code with any metric will also generate the corresponding L2 result with the name "mean_image.png".

Finding the E-LPIPS average of ten noisy images:
> python ex_bary10.py inputs/cat.png --mode=noise --outdir=out_bary10_cat_noise_elpips
Finding the E-LPIPS average of ten shifted images:
> python ex_bary10.py inputs/cat.png --mode=shift --outdir=out_bary10_cat_shift_elpips
Finding the corresponding LPIPS averages:
> python ex_bary10.py inputs/input_cat.png --mode=noise --metric=lpips_vgg --outdir=out_bary10_cat_noise_lpips_vgg
> python ex_bary10.py inputs/input_cat.png --mode=shift --metric=lpips_vgg --outdir=out_bary10_cat_shift_lpips_vgg

> python ex_bary10.py inputs/input_cat.png --mode=noise --metric=lpips_squeeze --outdir=out_bary10_cat_noise_lpips_sqz
> python ex_bary10.py inputs/input_cat.png --mode=shift --metric=lpips_squeeze --outdir=out_bary10_cat_shift_lpips_sqz

train_run.py

Trains the LPIPS weights for a network. Can be used for both E-LPIPS and LPIPS. Use the script 'lpips_scripts/download_dataset.sh' included from the original LPIPS distribution to download the dataset.

The training script will pre-process the datasets into single-file datasets in the Darc format (darc.py) before use. This will take some time, but will immensely speed up training at least on some environments.

An example script 'train_squeeze_ensemble.sh' is provided for training a SqueezeNet version of E-LPIPS, with max pooling instead of average pooling since the average pooled version would require re-training SqueezeNet.

The custom weights stored in numpy format can be taken into use by the flag 'custom_lpips_weights' given to the constructor of class elpips.Metric.

train_test_2afc.py

Runs the 2AFC test for a model. See file 'train_test_2afc_squeeze_example.sh' for an example.

elpips's People

Contributors

harskish avatar mkettune avatar

Watchers

James Cloos avatar paper2code - bot avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.