Search code examples
pythonscipyinterpolationbicubicbilinear-interpolation

Does bilinear/bicubic interpolation operate on each color channel independently?


I'm using scipy.ndimage.interpolation.zoom with either bilinear interpolation or bicubic interpolation (order=1 or 3, if I'm correct).

https://docs.scipy.org/doc/scipy-0.15.1/reference/generated/scipy.ndimage.interpolation.zoom.html

When working with an RGB image, do the bilinear/bicubic interpolation algorithms operate independently on each color channel, or is there some dependency between color channels?


Solution

  • ndimage.interpolation.zoom does not have a concept of RGB channels; it zooms an arbitrary n-dimensional array without any particular meaning to each dimension. For example, if you have an image stored as an array of shape (20, 20, 3) then after zoom(image, 2) it will become an array of shape (40, 40, 6) which is of course undesirable.

    Presumably you will use zoom(image, (2, 2, 1)) to have 2x zoom in both dimensions and no "zoom" in the channel dimension. If so, there is no spillover between channels then. Reading the C code of NI_ZoomShift I see that zoom is achieved using get_spline_interpolation_weights which performs one-dimensional spline interpolation (not bilinear or bicubic). This means that the zoom will consist of:

    1. Going over every 1D slice image[:, c, ch] and zooming it by 1D interpolation (no interaction between slices).
    2. Going over every 1D slice image[r, :, ch] and zooming it by 1D interpolation.
    3. Going over every 1D slice image[r, c, :] and zooming it by 1D interpolation - which with zoom factor of 1 will leave the values the same up to machine precision.

    A test of the above: zooming the entire image vs zooming each channel separately.

    import numpy as np
    from scipy.ndimage.interpolation import zoom
    image = np.random.uniform(size=(20, 20, 3))
    output = zoom(image, (2, 2, 1))
    for k in range(3):
        output_channel = zoom(image[:, :, k], 2)
        print(np.max(np.abs(output_channel - output[:, :, k])))
    

    The printed values are around 1e-15, i.e., the output is the same up to floating point errors.