4

Is there any numpy or scipy or python function to interpolate between two 2D numpy array's? I have two 2D numpy arrays, and I want to apply changes to the first numpy array to make it similar to the second 2D array. The constraint is that I want the changes to be smooth. e.g., let the arrays be:

A
[[1 1 1
  1 1 1
  1 1 1]]

and

B
[[34  100 15
  62  17  87
  17  34  60]]

To make A similar to B, I could add 33 to the first grid cell of A and so on.. However, to make the changes smoother, I plan to compute a mean using a 2x2 window on array B and then apply the resulting changes to array A. Is there a built in numpy or scipy method to do this or follow this approach without using for loop.

3
  • 1
    Could you explain more clearly what you mean by "computing a mean" and "applying the resulting changes to array A"? Commented Oct 8, 2016 at 6:19
  • 1
    Also, what does “make A similar to B” mean, precisely? Could you add the loop you’re trying to avoid? It would greatly help figure out the result you want to produce. Commented Oct 12, 2016 at 9:53
  • Or even add just the resulting matrix so we know the desired result you intend for this case. Commented Oct 12, 2016 at 22:10

2 Answers 2

2

You've just described a Kalman Filtering / data fusion problem. You have an initial state A that has some errors and you have some observations B that also have some noise. You want to improve your estimate of state A by injecting some information from B, all while accounting for spatially correlated errors in both datasets. We don't have any prior information about the errors in A and B, so we can just make it up. Here's an implementation:

import numpy as np

# Make a matrix of the distances between points in an array
def dist(M):
    nx = M.shape[0]
    ny = M.shape[1]
    x = np.ravel(np.tile(np.arange(nx),(ny,1))).reshape((nx*ny,1))
    y = np.ravel(np.tile(np.arange(ny),(nx,1))).reshape((nx*ny,1))
    n,m = np.meshgrid(x,y)
    d = np.sqrt((n-n.T)**2+(m-m.T)**2)
    return d

# Turn a distance matrix into a covariance matrix. Here is a linear covariance matrix.
def covariance(d,scaling_factor):
    c = (-d/np.amax(d) + 1)*scaling_factor
    return c

A = np.array([[1,1,1],[1,1,1],[1,1,1]]) # background state
B = np.array([[34,100,15],[62,17,87],[17,34,60]]) # observations

x = np.ravel(A).reshape((9,1)) # vector representation
y = np.ravel(B).reshape((9,1)) # vector representation

P_a = np.eye(9)*50 # background error covariance matrix (set to diagonal here)
P_b = covariance(dist(B),2) # observation error covariance matrix (set to a function of distance here)

# Compute the Kalman gain matrix
K = P_a.dot(np.linalg.inv(P_a+P_b))

x_new = x + K.dot(y-x)
A_new = x_new.reshape(A.shape)

print(A)
print(B)
print(A_new)

Now, this method only works if your data are unbiased. So mean(A) must equal mean(B). But you'll still get okay results regardless. Also, you can play with the covariance matrices however you like. I'd recommend reading the Kalman filter wikipedia page for more details.

By the way, the example above yields:

[[ 27.92920141  90.65490699   7.17920141]
 [ 55.92920141   7.65490699  79.17920141]
 [ 10.92920141  24.65490699  52.17920141]]
Sign up to request clarification or add additional context in comments.

Comments

1

One way of smoothing could be to use convolve2d:

import numpy as np
from scipy import signal

B = np.array([[34, 100, 15],
              [62,  17, 87],
              [17,  34, 60]])
kernel = np.full((2, 2), .25)
smoothed = signal.convolve2d(B, kernel)
# [[  8.5   33.5   28.75   3.75]
#  [ 24.    53.25  54.75  25.5 ]
#  [ 19.75  32.5   49.5   36.75]
#  [  4.25  12.75  23.5   15.  ]]

The above pads the matrix with zeros from all sides and then calculates the mean of each 2x2 window placing the value at the center of the window.

If the matrices were actually larger, then using a 3x3 kernel (such as np.full((3, 3), 1/9)) and passing mode='same' to convolve2d would give a smoothed B with its shape preserved and elements "matching" the original. Otherwise you may need to decide what to do with the boundary values to make the shapes the same again.

To move A towards the smoothed B, it can be set to a chosen affine combination of the matrices using standard arithmetic operations, for instance: A = .2 * A + .8 * smoothed.

3 Comments

That does not use array A.
@JARS After smoothing B you could for instance calculate some affine combination of A and B, like: .2 * A + .8 * B. To make shapes of A and B match pass mode=same to convolve2d (and possibly use an odd kernel such as 3x3).
Done. With a judicious choice of the kernel you can achieve many different kinds of smoothing, one common example is the Gaussian blur from the field of image processing.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.