0

Imagine we have the following points:

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 3, 5.5, 6.5, 5, 4, 5, 7.5, 8, 7]

enter image description here

Now we want to interpolate every point using lanczos interpolation like:

lanczos_interpolation = lanczos_interpolation(x, y)
xs = np.linspace(0, 10, 100)
interpolated_xs = lanczos_interpolation(xs)

How can I implement the lanczos_interpolation? I have already seen interpolate.interp1d but lanczos is not available...

I want something that if plotted would look like (the provided example is with bilinear interpolation): enter image description here

Christoph Rackwitz
  • 11,317
  • 4
  • 27
  • 36
Janikas
  • 418
  • 1
  • 8
  • The wanted result is a line! :) – Janikas Aug 04 '22 at 21:40
  • The number of points can be like 100, I just want to interpolate the points provided as x,y – Janikas Aug 04 '22 at 21:45
  • Sorry, fixed it! The plots had the corret number of x points (starting in 1) – Janikas Aug 04 '22 at 21:49
  • Lanczos interpolation is not defined (AFAIK) for inputs at arbitrary points. You need input data samples at regular intervals. You happen to have an example with x values at integer coordinates, but it is not clear if this is always the case? – Cris Luengo Aug 05 '22 at 00:23

1 Answers1

2

This is the OpenCV Lanczos interpolation.

EDIT: Open CV interpolates for images, so actually it extrapolates data, because the starting points are pixels, and an image with more pixels, since it has smaller pixels, it has pixels outside the original range:

For example, on this image, initially there are 2 pixels, but if OpenCV is asked to interpolate to 20 smaller pixels, there would be 5 extra pixels on each side of the image. That is why the interpolation doesn't match. enter image description here

Unfortunately, this means that this method cannot interpolate between points at arbitrary coordinates. The original points have to have a constant separation.

This code does a dirty approximation, because there is no guarantee that the pixels will match exactly:


import numpy as np
import matplotlib.pyplot as plt
import cv2

x = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
y = [2, 3, 5.5, 6.5, 5, 4, 5, 7.5, 8, 7]

img = np.array([y])
parts = 100
xs = np.linspace(1, 10, parts)
resized = cv2.resize(img, (int(parts*(1+1/len(y))), 1),
                     interpolation=cv2.INTER_LANCZOS4)[0]

plt.scatter(x, y)
plt.plot(xs, resized[int(parts/(2*len(y))):int(parts/(2*len(y)))+parts])
plt.show()

enter image description here

Colim
  • 1,283
  • 3
  • 11
  • Thank you! Should't it be alined with the points? – Janikas Aug 04 '22 at 22:14
  • I think the problem might be that we are not fitting the points to the interpolation? For example using `scipy.interpolate.interp1d` we first need to pass x and y before interpolating with xs – Janikas Aug 04 '22 at 22:25
  • Why lanczos? Why not a cubic or quadratic, so you can use scipy? – Colim Aug 04 '22 at 22:38
  • I already made the code for 1D bicubic (cubic), 1D bilinear (linear) and 1D nearest with scipy. I need to make lanczos as well as a mens to compare them. Do you know any other solution? – Janikas Aug 04 '22 at 22:44
  • Lanczos is a convolution with a mexican hat function. So you may generate the mexican hat, and use a convolution. Ask the people on wavelets, most probably they already have it under another name. – Colim Aug 04 '22 at 22:55
  • 2
    there is no "bug" in OpenCV, at least not with Lanczos. this is the expected result. the interpolation is not required to pass through the points. -- _maybe_ the issue could be the coordinate systems of OpenCV, how `src` is mapped to `dst` given a desired size. – Christoph Rackwitz Aug 04 '22 at 23:13
  • Is there something useful in this link https://docs.scipy.org/doc/scipy/reference/interpolate.html#module-scipy.interpolate? – Janikas Aug 04 '22 at 23:16
  • @ChristophRackwitz I understand what you said, but why do bilinear and bicubic interpolations pass through the points but lanczos doesn't? I want to fill/interpolate in the middle of the points – Janikas Aug 04 '22 at 23:18
  • @ChristophRackwitz is there any way this can be useful to build an interpolation that passes through the points? https://docs.scipy.org/doc/scipy/reference/generated/scipy.special.sinc.html – Janikas Aug 04 '22 at 23:47
  • 2
    @ChristophRackwitz It is not interpolation if it doesn’t pass through the input data points. The problem is that OpenCV resize does weird things with the coordinate system. – Cris Luengo Aug 05 '22 at 00:21
  • sure, interpolation, by definition, must have that property. -- *if* lanczos is merely a convolution of some kind... a kernel centered on a certain data point and applied to the signal is *not required* to equal that data point. -- given that the answer was edited to show that the values _do_ line up, I guess *lanczos* does make that guarantee. -- I never use cv.resize unless I don't particularly care... when I need precision, I use warpAffine and a custom matrix. sadly that no longer allows INTER_AREA... – Christoph Rackwitz Aug 05 '22 at 08:21