Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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]}

enter image description here

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!

share|improve this question
1  
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
1  
Szabolcs, I am assuming the values are sampled on a rectangular grid/lattice. –  Steve Apr 26 '13 at 15:00

1 Answer 1

up vote 4 down vote accepted

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:

enter image description here

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

share|improve this answer
1  
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
1  
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.. –  Steve Apr 26 '13 at 14:52
3  
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]; –  Steve Apr 29 '13 at 6:30

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.