Skip to main content

Fast differentiable resizing and warping of arbitrary grids

Project description

Hugues Hoppe    Aug 2022.

[Open in Colab]   [Kaggle]   [MyBinder]   [DeepNote]   [GitHub source]   [API docs]   [PyPI package]

The notebook resampler_notebook.ipynb hosts the source code for the resampler library in PyPI, interleaved with documentation, usage examples, unit tests, and signal-processing experiments.

Overview

The resampler library enables fast differentiable resizing and warping of arbitrary grids. It supports:

  • grids of any dimension (e.g., 1D, 2D images, 3D video, 4D batches of videos), containing

  • samples of any shape (e.g., scalars, colors, motion vectors, Jacobian matrices) and

  • any numeric type (integer, floating, and complex);

  • either dual ("half-integer") or primal grid-type for each dimension;

  • many boundary rules, specified per dimension, extensible via subclassing;

  • an extensible set of filter kernels, selectable per dimension;

  • optional gamma transfer functions for correct linear-space filtering;

  • prefiltering for accurate antialiasing when downsampling;

  • processing within several array libraries (numpy, tensorflow, torch, and jax);

  • efficient backpropagation of gradients for tensorflow, torch, and jax;

  • easy installation, with no native code, yet

  • faster resizing than C++ implementations in tf.image, torch.nn, and torchvision.

A key strategy is to leverage existing sparse matrix representations and operations.

Example usage

!pip install -q mediapy resampler
import mediapy as media
import numpy as np
import resampler
array = np.random.default_rng(1).random((4, 6, 3))  # 4x6 RGB image.
upsampled = resampler.resize(array, (128, 192))  # To 128x192 resolution.
media.show_images({'4x6': array, '128x192': upsampled}, height=128)
image = media.read_image('https://github.com/hhoppe/data/raw/main/image.png')
downsampled = resampler.resize(image, (32, 32))
media.show_images({'128x128': image, '32x32': downsampled}, height=128)
import matplotlib.pyplot as plt
array = [3.0, 5.0, 8.0, 7.0]  # 4 source samples in 1D.
new_dual = resampler.resize(array, (32,))  # (default gridtype='dual') 8x resolution.
new_primal = resampler.resize(array, (25,), gridtype='primal')  # 8x resolution.
_, axs = plt.subplots(1, 2, figsize=(7, 1.5))
axs[0].set_title('gridtype dual')
axs[0].plot((np.arange(len(array)) + 0.5) / len(array), array, 'o')
axs[0].plot((np.arange(len(new_dual)) + 0.5) / len(new_dual), new_dual, '.')
axs[1].set_title('gridtype primal')
axs[1].plot(np.arange(len(array)) / (len(array) - 1), array, 'o')
axs[1].plot(np.arange(len(new_primal)) / (len(new_primal) - 1), new_primal, '.')
plt.show()
batch_size = 4
batch_of_images = media.moving_circle((16, 16), batch_size)
upsampled = resampler.resize(batch_of_images, (batch_size, 64, 64))
spacer = np.ones((64, 16, 3))
media.show_images([*batch_of_images, spacer, *upsampled], border=True, height=64)
media.show_videos({'original': batch_of_images, 'upsampled': upsampled}, fps=1)

original

upsampled

Most examples above use the default resize() settings:

  • gridtype='dual' for both source and destination arrays,
  • boundary='auto' which uses 'reflect' for upsampling and 'clamp' for downsampling,
  • filter='lanczos3' (a Lanczos kernel with radius 3),
  • gamma=None which by default uses the 'power2' transfer function for the uint8 image in the second example,
  • scale=1.0, translate=0.0 (no domain transformation),
  • default precision and output dtype.

Advanced usage:

Map an image to a wider grid using custom scale and translate vectors, with horizontal 'reflect' and vertical 'natural' boundary rules, providing a constant value for the exterior, using different filters (Lanczos and O-MOMS) in the two dimensions, disabling gamma correction, performing computations in double-precision, and returning an output array in single-precision:

new = resampler.resize(
    image, (128, 512), boundary=('natural', 'reflect'), cval=(0.2, 0.7, 0.3),
    filter=('lanczos3', 'omoms5'), gamma='identity', scale=(0.8, 0.25),
    translate=(0.1, 0.35), precision='float64', dtype='float32')
media.show_images({'image': image, 'new': new})

Warp an image by transforming it using polar coordinates:

shape = image.shape[:2]
yx = ((np.indices(shape).T + 0.5) / shape - 0.5).T  # [-0.5, 0.5]^2
radius, angle = np.linalg.norm(yx, axis=0), np.arctan2(*yx)
angle += (0.8 - radius).clip(0, 1) * 2.0 - 0.6
coords = np.dstack((np.sin(angle) * radius, np.cos(angle) * radius)) + 0.5
resampled = resampler.resample(image, coords, boundary='constant')
media.show_images({'image': image, 'resampled': resampled})

Limitations:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

resampler-0.3.5.tar.gz (38.8 kB view details)

Uploaded Source

Built Distribution

resampler-0.3.5-py3-none-any.whl (36.2 kB view details)

Uploaded Python 3

File details

Details for the file resampler-0.3.5.tar.gz.

File metadata

  • Download URL: resampler-0.3.5.tar.gz
  • Upload date:
  • Size: 38.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.9.13

File hashes

Hashes for resampler-0.3.5.tar.gz
Algorithm Hash digest
SHA256 c9c0530dc33df1392c2ae0da91867ac40c8e0e788c1852e7880f2ea787b0d164
MD5 7b3ba6ef48b9338c9af77cb95cada162
BLAKE2b-256 15ffe109dd3b4dac6b1c6bc2ab28568f2089e9d7cc39812be1d72833efe22636

See more details on using hashes here.

File details

Details for the file resampler-0.3.5-py3-none-any.whl.

File metadata

  • Download URL: resampler-0.3.5-py3-none-any.whl
  • Upload date:
  • Size: 36.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.9.13

File hashes

Hashes for resampler-0.3.5-py3-none-any.whl
Algorithm Hash digest
SHA256 f84c3fc043970480458f3278cbf439fa77e1ddb8e63dd84be8b1b63c95b05000
MD5 493288b1b2fca4a936ca940d71f94625
BLAKE2b-256 25120b410230d4666f39a5106d0d883937d871ee3ed7ca674728e3c1b1c2b265

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page