Time comparison
In this notebook, the computation time of the ImWIP functions is measured and compared against the warping functions of SciPy, scikit-image and Open-CV.
[1]:
import numpy as np
import cupy as cp
import imwip
from skimage.transform import warp as scikit_warp
from scipy.ndimage import map_coordinates as scipy_warp
from cv2 import remap as cv_warp
from cv2 import INTER_CUBIC
Generating data
[2]:
im_size_2D = 2000
im_size_3D = 200
[3]:
im_2D = np.random.random((im_size_2D,)*2).astype(np.float32)
im_2D_raveled = im_2D.ravel()
u_2D = np.random.random((im_size_2D,)*2).astype(np.float32)
v_2D = np.random.random((im_size_2D,)*2).astype(np.float32)
[4]:
im_3D = np.random.random((im_size_3D,)*3).astype(np.float32)
im_3D_raveled = im_3D.ravel()
u_3D = np.random.random((im_size_3D,)*3).astype(np.float32)
v_3D = np.random.random((im_size_3D,)*3).astype(np.float32)
w_3D = np.random.random((im_size_3D,)*3).astype(np.float32)
[5]:
# DVF in absolute format (ImWIP uses relative format)
i, j = np.meshgrid(
np.arange(im_size_2D),
np.arange(im_size_2D),
indexing="ij"
)
map_i_2D = (u_2D + i).astype(np.float32)
map_j_2D = (v_2D + j).astype(np.float32)
map_2D = np.array([map_i_2D, map_j_2D])
[6]:
# DVF in absolute format (ImWIP uses relative format)
i, j, k = np.meshgrid(
np.arange(im_size_3D),
np.arange(im_size_3D),
np.arange(im_size_3D),
indexing="ij"
)
map_i_3D = (u_3D + i).astype(np.float32)
map_j_3D = (v_3D + j).astype(np.float32)
map_k_3D = (w_3D + k).astype(np.float32)
map_3D = np.array([map_i_3D, map_j_3D, map_k_3D])
Timing
3D warps
ImWIP, cpp backend, including copy to and from GPU:
[7]:
%timeit -r 10 -n 10 imwip.warp(im_3D, u_3D, v_3D, w_3D, degree=3, backend="cpp")
77.3 ms ± 4.83 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)
ImWIP, Numba backend, including copy to and from GPU:
[9]:
%timeit -r 10 -n 10 imwip.warp(im_3D, u_3D, v_3D, w_3D, degree=3, backend="numba")
91.5 ms ± 439 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
ImWIP, Numba backend, arrays preloaded on GPU:
[10]:
# converting numpy arrays to cupy arrays on GPU
im_3D_gpu = cp.asarray(im_3D)
u_3D_gpu = cp.asarray(u_3D)
v_3D_gpu = cp.asarray(v_3D)
w_3D_gpu = cp.asarray(w_3D)
[11]:
%timeit -r 10 -n 10 imwip.warp(im_3D_gpu, u_3D_gpu, v_3D_gpu, w_3D_gpu, degree=3, backend="numba")
62 ms ± 928 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
[12]:
# freeing the GPU memory
del im_3D_gpu, u_3D_gpu, v_3D_gpu, w_3D_gpu
SciPy
[13]:
%timeit -r 10 -n 10 scipy_warp(im_3D, map_3D, order=3)
1.87 s ± 12 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)
scikit-image
[14]:
%timeit -r 10 -n 10 scikit_warp(im_3D, map_3D, clip=False, order=3)
2.74 s ± 16 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)
2D warps
ImWIP, cpp backend, including copy to and from GPU:
[15]:
%timeit -r 10 -n 10 imwip.warp(im_2D, u_2D, v_2D, degree=3, backend="cpp")
13.5 ms ± 636 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
ImWIP, Numba backend, including copy to and from GPU:
[17]:
%timeit -r 10 -n 10 imwip.warp(im_2D, u_2D, v_2D, degree=3, backend="numba")
19.8 ms ± 539 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
ImWIP, Numba backend, arrays preloaded on GPU:
[18]:
# converting numpy arrays to cupy arrays on GPU
im_2D_gpu = cp.asarray(im_2D)
u_2D_gpu = cp.asarray(u_2D)
v_2D_gpu = cp.asarray(v_2D)
[19]:
%timeit -r 10 -n 10 imwip.warp(im_2D_gpu, u_2D_gpu, v_2D_gpu, degree=3, backend="numba")
8.47 ms ± 538 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
[20]:
# freeing the GPU memory
del im_2D_gpu, u_2D_gpu, v_2D_gpu
SciPy
[21]:
%timeit -r 10 -n 10 scipy_warp(im_2D, map_2D, order=3)
344 ms ± 1.58 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)
scikit-image
[22]:
%timeit -r 10 -n 10 scikit_warp(im_2D, map_2D, clip=False, order=3)
483 ms ± 1.19 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)
Open-CV (only 2D warps)
[23]:
%timeit -r 10 -n 10 cv_warp(im_2D, map_j_2D, map_i_2D, INTER_CUBIC)
5.95 ms ± 149 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
Adjoint warps
[24]:
%timeit -r 10 -n 10 imwip.adjoint_warp(im_2D, u_2D, v_2D, degree=3)
12.8 ms ± 656 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
[25]:
%timeit -r 10 -n 10 imwip.adjoint_warp(im_3D, u_3D, v_3D, w_3D, degree=3)
67.1 ms ± 847 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
Differentiated warps
[26]:
%timeit -r 10 -n 10 imwip.diff_warp(im_2D, u_2D, v_2D)
20.4 ms ± 403 µs per loop (mean ± std. dev. of 10 runs, 10 loops each)
[27]:
%timeit -r 10 -n 10 imwip.diff_warp(im_3D, u_3D, v_3D, w_3D)
196 ms ± 1.36 ms per loop (mean ± std. dev. of 10 runs, 10 loops each)
[ ]: