Suppose there are two curves (described by two groups of data): curve 1 and curve 2. The two curves have more than two intersection points. A new curve 3 is obtained by keeping the upper part of the two curves. The problem is that there are several sharp corners at the intersection points on curve 3. How to smooth the curve by rounding off these corners using matlab?
Asked
Active
Viewed 2,899 times
2 Answers
3
Apply a convolution with a lowpass filter?
n = 4; %// adjust as needed. Higher value gives more smoothing
curve3_smooth = conv(curve3, ones(1,n)/n, 'same');
A better idea, as noted by @Hoki, is to apply the filter twice: once forwards and once backwards, to make the smoothing operation symmetric. You can achieve that with filtfilt
:
n = 2;
curve3_smooth = filtfilt(ones(1,n)/n, 1, curve3);

Luis Mendo
- 110,752
- 13
- 76
- 147
-
1Nice! no need to call any fancy filter function. May be you should just add the option to re-run the filter in reverse to get a zero-phase result (in case it is important for his curves): `curve3_smooth_noPhaseShift = fliplr( conv(fliplr(curve3_smooth), ones(1,n)/n, 'same') ) ;` – Hoki Sep 22 '14 at 12:55
-
Thanks! In conv(u,v,'same'), u and v should be vectors. In my case u is a mx2 matrix. How to apply this command? – open0121 Sep 22 '14 at 12:59
-
@open0121 Are you saying you have a matrix whose rows store `x` and `y` coords? Are they stored in a sensible order (like a parameterising variable `t` for example)? Because then you can just use `conv2` instead of `conv` and also use a column vector for your kernel so `ones(n,1)/n` – Dan Sep 22 '14 at 13:15
-
@Dan The matrix stores x and y coordinates of points, but not in a sensible order. – open0121 Sep 22 '14 at 13:30
-
@open0121 if you connect the x-y pairs in the sequence you have stored them and you get the curve you expect, then that is what I mean by a sensible (parameterised) order. `conv2` will most likely work for you – Dan Sep 22 '14 at 13:34
-
@Luis Mendo. Thank you! I tried and found that the new curve was not in the same scale as the original one. it was scaled 4:1. No idea why this happens although it is easy to re-scale the curve. – open0121 Sep 22 '14 at 14:27
-
@open0121 I've tried both approaches with `curve3 = 2*ones(1,20); curve3(5) = 4;` and it seems to work fine: the output is mostly `2` and the `4`is smoothed out – Luis Mendo Sep 22 '14 at 14:49
1
Borrowing from Luis Mendo's post and your comments in his post, if you are given 2D data where each column is a single vector and you want to filter each of the columns separately, then use filter
instead. You'd specify the dimension to be 1
, as you want to filter along the rows. As such:
%// adjust as needed
n = 4;
smooth_curve = filter(ones(1,n)/n, 1, u, [], 1);

rayryeng
- 102,964
- 22
- 184
- 193
-
Thanks! I got a smooth curve but always with an extra segment on the curve. No idea how to get rid of the extra segment. – open0121 Sep 22 '14 at 13:33
-
-
there are extra points on the new curve besides the smoothed curve with similar shape as original curve, which 'destroys' the similarity. With filtfilt(ones(n,2)/n, 1, u) the extra points are removed, but the new curve is not in the same scale as the original one... – open0121 Sep 22 '14 at 14:23
-
Where do these extra points occur? Can you show me what this looks like? It's really hard to visualize. You don't have enough reputation to post an image, so post it on [`imgur`](http://imgur.com/) or some other public sharing website so I can see the results. – rayryeng Sep 22 '14 at 14:33