# FLIP turns the difference between two renders into something you can look at

> FLIP is NVIDIA's perceptual image difference metric, shipped as a Python package, a single C++ header with an optional CUDA backend, and a PyTorch loss module. It is designed to be read rather than just scored, which is its strength and also the reason its version history and precision notes matter when you compare numbers.

**NVlabs/flip** — A tool for visualizing and communicating the errors in rendered images.

- Repository: https://github.com/NVlabs/flip
- Stars: 658 · Forks: 56
- Language: C++
- License: NOASSERTION
- Published: 2026-10-21 · Updated: 2026-10-21 · Language: en
- Canonical page: https://hysenlabs.com/projects/nvlabs-flip

## A metric designed to be looked at

The description is short and unusual for a tool in graphics: a tool for visualizing and communicating the errors in rendered images. Most image comparison metrics give you a number and a difference image, and the number is what people report. FLIP is built so that the spatial error map is the primary output, with the score derived from the same computation.

The repository holds implementations of the LDR-FLIP and HDR-FLIP image error metrics, and also the code for the FLIP tool presented in Ray Tracing Gems II. The distinction between the two matters for citation. If your work uses the tool to find errors between low dynamic range images, the README asks you to cite the LDR-FLIP paper, and for high dynamic range images the HDR-FLIP paper, with BibTeX links for both, and a third citation for the general Ray Tracing Gems II article.

The authorship list explains the audience. Pontus Ebelin and Tomas Akenine-Möller lead, with Jim Nilsson, Magnus Oskarsson, Kalle Åström, Mark D. Fairchild and Peter Shirley, a mix of rendering researchers and colour science people. The colour science connection is the point: a perceptual metric needs a perceptual model, and that is where the difficulty in this problem lives.

The repository also links an image gallery displaying a large quantity of reference and test images with corresponding error maps from different metrics, which is the most direct way to understand what the tool is for.

## Three entry points: a Python tool, a header, a loss

The project is distributed for three different kinds of user, and the README is organised around exactly that.

The simplest way to get started is the Python package, and the README calls it the simplest way to run FLIP to compare a test image to a reference image:

```
pip install flip-evaluator
flip -r referenceImage.png -t testImage.png
```

For more about what the tool can do, the README suggests running `flip -h`. The Python section says it requires Python 3.10 or newer, and points to an example script `src/python/api_example.py` for the API, alongside the tool form `flip --reference reference.{exr|png} --test test.{exr|png} [--options]`.

The C++ and CUDA section exposes the same two shapes, an API and a tool, with the tool invocation written as `flip[-cuda].exe --reference reference.{exr|png} --test test.{exr|png} [options]`.

The third is the PyTorch loss function, which is the version for people training models rather than comparing finished frames. LDR- and HDR-FLIP are implemented as loss modules in `src/pytorch/flip_loss.py`, and there is an example training a simple autoencoder in `src/pytorch/train.py`.

Note the pip package name, `flip-evaluator`, which is not the same as the repository name. The README records that since v1.6 the Python version of FLIP can be installed this way, which is a detail worth knowing if you are following older instructions.

## One header for C++, with CUDA as a switch

The C++ integration is deliberately minimal. Since v1.3 the project switched to a single header, `FLIP.h` in `src/cpp/`, for easier integration. For a renderer that already has a build system, that is the whole integration story: include one header, and the metric is available in your own pipeline rather than only through the command line tool.

Builds come in two flavours. The `src/cpp/FLIP.sln` solution contains one CUDA backend project and one pure C++ backend project, and compiling the CUDA project requires a CUDA compatible GPU. Alternatively a CMake build can be done by creating a build directory in the `src` directory and invoking CMake on the source `cpp` directory:

```
cd src
mkdir build
cd build
cmake ..
cmake --build . [--config Release]
```

The README notes that adding `--config Release` builds the release configuration on Windows, and that CUDA support is enabled via `FLIP_ENABLE_CUDA`, which can be passed to CMake on the command line with `-DFLIP_ENABLE_CUDA=ON` or set interactively with `ccmake` or `cmake-gui`. There is also a `FLIP_LIBRARY` option that allows you to output a library rather than an executable, which is what you want if you are embedding the metric in another renderer rather than comparing two files from the command line.

So the C++ story is: one header to include, a pure C++ path that needs no GPU, and a CUDA path for the throughput you would want inside a renderer.

## The PyTorch path is a differentiator, with a setup cost

The loss function is the part of FLIP that is unusual in a rendering tool, because it puts a perceptual metric inside a training loop.

The setup in the README uses a Conda environment:

```
conda create -n flip_dl python numpy matplotlib
conda activate flip_dl
conda install pytorch torchvision torchaudio cudatoolkit=11.1 -c pytorch -c conda-forge
conda install -c conda-forge openexr-python
```

Two things stand out. The `cudatoolkit=11.1` pin is specific, and `openexr-python` is needed because FLIP reads and writes EXR images, which is the format for high dynamic range content.

The README also repeats a warning that is easy to miss: remember to activate the `flip_dl` environment through `conda activate flip_dl` before using the loss function. That is a sharp edge in an otherwise smooth path, since a forgotten activation gives you an import error rather than a clear message.

The point of the loss module is that a training run can optimise for perceptual similarity rather than for a squared error against pixels, and the autoencoder example in `src/pytorch/train.py` shows the intended shape of that code. Whether that is the right objective for your problem is a research question the repository does not answer, but it does make the metric usable as more than a comparison tool.

## Version notes that change what you measure

The README's notes about specific versions are short and each one describes a behaviour change, which is exactly the kind of thing that breaks a comparison against a published number.

Since v1.7, the automatic stop exposure in HDR-FLIP is able to handle reference images whose median luminance is 0. That sounds like an edge case, and for a viewer it is, but for an HDR workflow it is a difference between producing a result and producing a failure, and it changes the behaviour of an existing pipeline.

Since v1.6, the Python version can be installed via `pip install flip-evaluator`, and since v1.3 the C++ and CUDA side is a single header. The changes made for the different versions of FLIP are summarized in a version list document in the repository, which is the file to read before comparing your output with a number from a paper.

There is also a note about the precision of FLIP in the repository, and a list of papers that use or cite FLIP. The existence of a precision note says something useful: a perceptual metric is a model with parameters, and the numbers it produces depend on those parameters as well as on the images.

The practical advice is unglamorous. Record which version produced a number, because the version list exists precisely because the results are not identical across releases, and read the precision note before you quote a figure next to someone else's.

## Three licences in one repository

The licensing section is worth reading carefully, because it covers three separate things.

The work itself is under a BSD 3-Clause License, with the copyright line reading Copyright 2020-2025, NVIDIA Corporation & Affiliates. The repository also distributes code for `tinyexr`, which is subject to a BSD 3-Clause License, and `stb_image`, which is subject to an MIT License, both documented in the third party licence file. So the tool you install pulls in two image libraries under their own terms, and the notices are collected rather than scattered.

The third element is contributions. For individual contributions to the project, the README asks contributors to confer the Individual Contributor License Agreement, and for business inquiries it points to the NVIDIA Research Licensing form on the website.

One caveat to note for anyone checking the licence from a repository page. The repository metadata for this project classifies the licence as one GitHub cannot categorise, while the README states BSD 3-Clause, and the `pyproject.toml` header carries the full BSD 3-Clause text with an SPDX identifier of BSD-3-Clause. The `LICENSE` file at the root is the document to read, and this is not legal advice, only a pointer to the file that settles it.

## When a scalar metric is the better answer

FLIP is a comparison tool for two images, and it is a good one, but it is not a general replacement for every way of measuring image difference.

The first constraint is input. FLIP compares a reference image with a test image, so you need both, and they have to correspond. That makes it a tool for render comparison, for regression testing between two versions of a frame, or for evaluating a reconstruction, and a poor fit for a task where you have a reference and a stream of output, or where you want a quality score for an image that has no counterpart.

The second is what you need the answer for. FLIP is designed so the error map is readable, and that is its strength, but a readable map is not always what a pipeline wants. A regression test in CI wants a threshold on a number, and a number is easier to threshold than a picture. A classical metric such as PSNR or SSIM gives you a scalar, and comparing it against a historical value is trivial.

The difference in approach is exactly this. A scalar metric compresses the whole difference into one figure and loses the spatial information; FLIP keeps the spatial distribution and derives its score from the same computation. If your problem is regression detection, the scalar is usually enough and cheaper. If your problem is finding out why the frame is wrong, and where, then the map is the thing you need and FLIP is the right tool.

The version list and the precision note are the two files to read before you publish a FLIP number, because a perceptual metric that changes between releases is a metric you have to pin.

## Conclusion

Adopt FLIP when you need to see where two renders differ rather than only how much they differ, when you are working with low or high dynamic range images from a renderer, and when you can pin a version of the metric. Do not adopt it as a drop-in replacement for a scalar metric in an existing pipeline without reading the precision note and the version list, because the output changes between releases. Verify first that your reference and test images are aligned and in the same colour space, that you use the variant that matches your images, since LDR-FLIP and HDR-FLIP are separate papers with separate citations, and that the Python environment is 3.10 or newer for the `flip-evaluator` package.

## FAQ

### How do I install and run FLIP?

Install the Python package with `pip install flip-evaluator`, which needs Python 3.10 or newer, and compare two images with `flip -r referenceImage.png -t testImage.png`. Run `flip -h` for the full option list, and see `src/python/api_example.py` for using the API from Python.

### What is the difference between LDR-FLIP and HDR-FLIP?

They are separate metrics for separate image types, described in separate papers. The README asks you to cite the LDR-FLIP paper when your work compares low dynamic range images and the HDR-FLIP paper for high dynamic range images, with the Ray Tracing Gems II article for more general use.

### How do I build the C++ and CUDA version of FLIP?

Create a build directory in the src directory and invoke CMake on the cpp source, then build it. CUDA support is enabled with `-DFLIP_ENABLE_CUDA=ON` or interactively with ccmake or cmake-gui, and the FLIP_LIBRARY option makes CMake output a library rather than an executable. The solution file also offers a pure C++ backend that needs no CUDA GPU.

### Can FLIP be used as a PyTorch loss function?

Yes. LDR- and HDR-FLIP are implemented as loss modules in src/pytorch/flip_loss.py, with an autoencoder training example in src/pytorch/train.py. The README's setup uses a conda environment with pytorch, torchvision, torchaudio, cudatoolkit=11.1 and openexr-python, and reminds you to activate that environment before using the loss function.

## Sources

- [Issues](https://github.com/NVlabs/flip/issues)
- [NVlabs/flip on GitHub](https://github.com/NVlabs/flip)
- [README](https://github.com/NVlabs/flip/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/nvlabs-flip
