espdev / sgolay2

Two-dimensional Savitzky-Golay filter
MIT License
29 stars 10 forks source link

Is it possible to apply this to a 2D signal (x,y position)? #3

Closed Cram3r95 closed 1 year ago

Cram3r95 commented 2 years ago

Hi, this is an amazing content. I would like to filter my 2D signal to obtain both the velocity and acceleration at a time t, in order to estimate a CTRA model. Which method would you recommend to me? I am using the Argoverse Motion Forecasting dataset.

An example of what I am trying to do is as following:

imagen

espdev commented 2 years ago

Hello @Cram3r95,

sgolay2 works only for surfaces on regular Cartesian grids.

You can consider csaps smoothing for your task. See the documentation for multivariate smoothing (2D case): https://csaps.readthedocs.io/en/latest/tutorial.html#multivariate-smoothing

If you need to use sgolay filtering, you can use 1D savgol_filter from scipy and parametrize by parameter t for x and y separately.

Cram3r95 commented 2 years ago

Got it. I would like to preserve the velocity and acceleration information, not to obtain equidistant points. If I conduct a separate filtering for each coordinate, and then join then, is this correct?

espdev commented 2 years ago

These are not necessarily equidistant points. It all depends on the t data site grid. Could you provide a sample of your data?

espdev commented 2 years ago

If I conduct a separate filtering for each coordinate, and then join then, is this correct?

Yes, you can use 1-D savgol filter for each coordinate.

Cram3r95 commented 2 years ago

Here is my data:

(Pdb) x array([-0.31418146, -0.32084206, -0.43827689, -0.43749745, -0.40649263, -0.24785958, -0.21867927, -0.21718585, -0.20703234, -0.1752735 , -0.04367442, -0.30753632, -0.14336099, -0.01123529, -0.11978056, -0.10602833, -0.08356585, 0.10507356, 0.12562331, 0. ])

(Pdb) y array([14.48325329, 14.00158717, 13.2696119 , 12.78406973, 11.74274226, 11.55458092, 11.06965875, 9.44117946, 8.8930401 , 8.3431558 , 7.56183614, 6.96244131, 6.65170151, 5.79408915, 4.25335575, 3.63905006, 3.0565611 , 2.19078549, 1.61893788, 0. ])

I could also implement a Bayesian filter solution, but first I want to explore a solution as efficient as possible -> I want to filter my signal in order to best estimate my velocity and acceleration in the last observation frame (that is, where X and Y are equal to 0, or the center of the image, as illustrated above).

espdev commented 2 years ago

For example:

import numpy as np
from scipy.signal import savgol_filter
import matplotlib.pyplot as plt

x = ...  # X data vector
y = ...  # Y data vector

xy = np.vstack((x, y))
xy_f = savgol_filter(xy, window_length=5, polyorder=3, axis=1)

x_f = xy_f[0, :]
y_f = xy_f[1, :]

plt.plot(x, y, ':o', x_f, y_f, '.-')
plt.show()
Cram3r95 commented 2 years ago

Yes, but doing this you are only smoothing one of the coordinates, right? Not both, since you assume one of them as the time-axis.

espdev commented 2 years ago

No, in this case we smooth both coordinates separately by axis=1.

For your sample we are getting: data_plot

Cram3r95 commented 2 years ago

This is another tricky example. The observation seems to present a constant velocity, but the observation is quite noisy.

imagen

Input data:

(Pdb) x array([-2.90470876, -2.45423747, -2.47054609, -2.15517243, -1.11500226, -1.01270935, -1.00007073, -0.76081561, -0.25430657, -0.47272535, -0.06071316, 0.07222567, -0.31588703, 0.13088221, -0.00530504, -0.0374395 , 0.20050868, 0.02133935, -0.16461405, 0. ]) (Pdb) y array([17.91807666, 17.18600004, 16.85460763, 16.12626906, 13.91504899, 13.24139842, 13.42173635, 12.01677173, 10.80650343, 10.13585118, 8.83081164, 8.03904163, 6.62514378, 5.91366662, 4.5361813 , 3.8069856 , 2.85839244, 1.56333415, 0.80128267, 0. ])

espdev commented 2 years ago

Could you try to use the code with savgol_filter and plot filtered data on your image?

Cram3r95 commented 2 years ago

Ah, got it, you stack both variables and then smooth along the time-axis, as a positional encoding, makes sense.

Cram3r95 commented 2 years ago

Yes, give me a moment. I assume that with this solution, we are going to get smoothed vectors with the same length (20 observations in this case), in order to not lose the positional information to compute the velocity and acceleration.

espdev commented 2 years ago

For second data sample I get: data_plot1

But we need to use right scaling of axes so that it makes sense.

Cram3r95 commented 2 years ago

Nice, I am integrating this code with the image. Please, try this:

imagen

(Pdb) x array([ 0.51638492, 0.24687597, 0.24687597, 0.61462248, 0.1597019 , 0.67346952, 0.55337124, 0.45054865, 0.45638668, 0.34816387, 0.31673042, 0.26071881, 0.26717796, 0.26230824, 0.1894866 , 0.23076022, 0.19717661, -0.06022335, 0.06737089, 0. ]) (Pdb) y array([-22.86125362, -22.1318296 , -22.1318296 , -19.69528495, -19.07734936, -16.82239551, -15.99187992, -15.15671999, -14.21899416, -12.36447778, -11.40892178, -10.2670728 , -9.35220874, -7.18156316, -6.22068484, -5.270861 , -4.20995223, -2.0349487 , -1.16746912, 0. ])

I am wondering if my Deep Learning model should have this noise in the input to prevent overfitting or a smoothed version of the input.

espdev commented 2 years ago

Is smoothing x and y by savgol_filter working right for you? It seems the approach preserves the velocity and acceleration information. And you don't have to set any grids.

I am wondering if my Deep Learning model should have this noise in the input to prevent overfitting or a smoothed version of the input.

I don't know, sorry. :) I think you need to experiment and try here.