4. Compare 2 videos with SSIM, PSNR and VMAF metrics

The classic metrics PSNR (Peak Signal to Noise Ratio) and SSIM (Structural SIMilarity) are implemented in C for improved performance.

[1]:
import pathlib
import subprocess
import tempfile

import matplotlib.pyplot as plt

from cutcutcodec.core.analysis.video.metric import compare
from cutcutcodec.core.io import read
from cutcutcodec.utils import get_project_root

4.1. Preparing videos to be compared

Here we’ll compare the original video with a noisy version.

[2]:
ref_file = get_project_root().parent / "media" / "video" / "intro.webm"
dis_file = pathlib.Path(tempfile.gettempdir()) / "distorded.mp4"

converter = subprocess.run(["ffmpeg", "-y", "-i", ref_file, dis_file], check=True, capture_output=True)  # transcode the video

4.2. Simple comparison of 2 videos or images

  • This function takes care of color spaces.

  • Image comparisons are always made in yuv, not rgb.

  • This function is optimized and parrallelized.

[3]:
metrics = compare(ref_file, dis_file, psnr=True, ssim=True)
compare: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 294/294 [00:30<00:00,  9.68img/s]
[4]:
plt.scatter(range(len(metrics["psnr"])), metrics["psnr"])
plt.xlabel("frames")
plt.ylabel("psnr (db)")
plt.show()

plt.scatter(range(len(metrics["ssim"])), metrics["ssim"])
plt.xlabel("frames")
plt.ylabel("ssim")
plt.show()
../../../_images/build_examples_basic_metrics_6_0.png
../../../_images/build_examples_basic_metrics_6_1.png

4.3. Compare frames manually for greater control

This makes it possible to specify the hyperparameters specific to each metric.

[5]:
ref_frame = read(ref_file).out_select("video")[0].snapshot(5.0, (1080, 1920))
ref_frame_numpy = ref_frame.numpy(force=True)
ref_frame.requires_grad = True
dis_frame = read(dis_file).out_select("video")[0].snapshot(5.0, (1080, 1920))
dis_frame_numpy = dis_frame.numpy(force=True)
dis_frame.requires_grad = True

4.3.1. Compare peak signal to noise ratio (PSNR)

  • This function has a C implementation (for cpu and no grad).

  • This function is torch differentiable.

[6]:
from cutcutcodec.core.analysis.video.metric import psnr

print(psnr(ref_frame_numpy, dis_frame_numpy))
print(psnr(ref_frame, dis_frame))
41.762505
tensor(41.7603, grad_fn=<ViewBackward0>)

4.3.2. Compare structural similarity index measure (SSIM)

  • This function has a C implementation (for cpu and no grad).

  • This function has a fft implementation (for stride = 1).

  • This function is torch differentiable.

[7]:
from cutcutcodec.core.analysis.video.metric import ssim

print(ssim(ref_frame_numpy, dis_frame_numpy))
print(ssim(ref_frame, dis_frame))

print(ssim(ref_frame_numpy, dis_frame_numpy, stride=2, sigma=1.2))
0.9862512
tensor(0.9863, grad_fn=<ViewBackward0>)
0.9870404

4.3.3. Compare Netflix VMAF

This function only allows efficient interfacing with the vmaf package. So you need to install vmaf.

[8]:
from cutcutcodec.core.analysis.video.metric import vmaf

print(vmaf(ref_frame_numpy, dis_frame_numpy))
45.14047