# Smoothing/Averaging 2D Vector Fields

I have a list of 2D vectors defined by {{x,y},{u,v}} and would like to smooth or average the vectors. For example here are 2 vector fields, the second has noise added to the orientation of each list item:

f = Sin[2 x + 2 y];
data = Flatten[Table[{{x, y}, {Cos[f], Sin[f]}}, {x, -1, 1, 0.1}, {y, -1, 1, 0.1}], 1];
noisydata = Flatten[ Table[
theRand = RandomReal[{-π/6, π/6}];
{{x, y}, {Cos[f + theRand], Sin[f + theRand]}}
, {x, -1, 1, 0.1}, {y, -1, 1, 0.1}], 1];
{ListVectorPlot[data], ListVectorPlot[noisydata]}
{ListStreamPlot[data], ListStreamPlot[noisydata]}


Any suggestions about smoothing the field in Mathematica? I am trying to interpolate the data (creating an interpolating function using Interpolation), but the resulting vector fields are very noisy. Any help would be appreciated!

-
If the vectors are in the form {{x,y}, {u,v}} then theoretically the vectors can be anywhere. In your specific example, they're on a regular lattice though, which would make the problem much simpler. Is your real data like this too? –  Szabolcs Apr 26 '13 at 14:33
Szabolcs, I am assuming the values are sampled on a rectangular grid/lattice. –  ChallengeResponse Apr 26 '13 at 15:00

There are many ways to de-noise data. A simple one is to use one of the built-in filters. For example here I've applied the MeanFilter separately to the x and y dimensions of the data points that make up the arrows (i.e., your noisydata). This is sensible because your points lie on a regular grid.

args = noisydata[[All, 1]];
datVals1 = MeanFilter[noisydata[[All, 2, 1]], 3];
datVals2 = MeanFilter[noisydata[[All, 2, 2]], 3];
denoised = Transpose[{args, Transpose[{datVals1, datVals2}]}];


Now add the plotting commands ListVectorPlot[denoised]} and ListStreamPlot[denoised] to get:

Other choices for filters might include GaussianFilter. You will probably want to do such smoothing before applying an interpolating function.

-
It should be noted that this exploits the fact that the {x,y} points are on a rectangular grid. –  Szabolcs Apr 26 '13 at 14:40
@szabolcs - exactly... I've added this in. –  bill s Apr 26 '13 at 14:44
Very nice. I'm wondering if applying a mean filter to u and v separately is a valid assumption for circular data though? Would it be more appropriate to assume constant vector magnitude and only average the orientations (which is modulo 2[Pi])? I found an article discussing this (april.eecs.umich.edu/pdfs/olson2011orientation.pdf) but have not yet implimented the code. However, I should note that my initial query was, "How does one smooth a vector field", not "How does one average vector field orientations". It would be great to clarify if this is generalizable.. –  ChallengeResponse Apr 26 '13 at 14:52
Whether it's "valid" or not depends on what you know about the source of the noise. If the noise is added independently at each point, then smoothing separately with a Gaussian (or more simply with a mean) should be fine. If the noise is correlated or comes about by some more complex mechanism, then you would need to take that into account. –  bill s Apr 26 '13 at 15:00
Using bill s' code snippet, I added normalization to force vector lengths of 1, making the resulting field reflect the average orientations: normalized = Map[{#[[1]], Normalize[#[[2]]]} &, denoised]; –  ChallengeResponse Apr 29 '13 at 6:30