3

I don't have the package for nlfilter and I didn't quite follow this example.

I have a really simple function fun and I want to apply it to a moving window of an array. The array is Nx1, and I want to look at length k intervals, say. So for N=10 and k=3 and fun = @(x) min(x); I would get

A = [13 14 2 14 10 3 5 9 15 8];

filter(A,k,fun) = [2 2 2 3 3 3 5 8];

Here I only want to look at indices 1,2,3 then 2,3,4 then ... then 8,9,10, so the final sequence is length 7. I can do this easy with a for loop, but I have no idea how to vectorize it for Matlab. Help, please. Thanks.

Community
  • 1
  • 1
WisaF
  • 314
  • 1
  • 3
  • 11
  • If you were looking for the minimum inside a window, you could use `imerode`, but unfortunately, that's in the image processing toolbox as well. – Jonas Nov 02 '11 at 12:35
  • another similar question with some good answers: [How do I select n elements of a sequence in windows of m ? (matlab)](http://stackoverflow.com/questions/7099590/how-do-i-select-n-elements-of-a-sequence-in-windows-of-m-matlab) – Amro Nov 09 '11 at 00:33

2 Answers2

6

Here is one very simple and fast way to do it:

>> min([A(1:(end-2)); A(2:(end-1)); A(3:end)], [], 1)

ans =

     2     2     2     3     3     3     5     8

EDIT: Since you want a full function...

function running_min = running_min(x, k)

xrep = repmat(x, 1, k);
xrep = reshape([xrep zeros(1, k)], length(x)+1, k);
running_min = min(xrep, [], 2)';
running_min = running_min(1:end-k);
John Colby
  • 22,169
  • 4
  • 57
  • 69
  • Thanks, but that only works for the example above when k=3. I need a function that takes k as an input. – WisaF Nov 02 '11 at 01:59
  • Downvote? The extension is trivial. I thought I'd leave that to you. See edit above. – John Colby Nov 02 '11 at 02:17
  • I didn't downvote (I don't even think I can). The extension isn't obvious to me. Thanks for elaborating. I still don't see how to input an arbitrary vector function, but this helps a lot. Thanks. – WisaF Nov 02 '11 at 03:37
  • No worries...it's totally my mistake. Good luck! – John Colby Nov 02 '11 at 03:55
4

The post you mentioned gave a general solution for building sliding windows (you could control: overlapping vs. distinct, slide step, overlap amount, windows size)

In your case, it is much simpler and can be easily performed with the HANKEL function:

x = [13 14 2 14 10 3 5 9 15 8];
idx = hankel(1:3, 3:length(x))
min( x(idx) )

If you want to build a reusable solution:

function y = myFilter(x,k,fcn)
    idx = hankel(1:k, k:length(x));
    y = cellfun(fcn, num2cell(x(idx),1));
end

which we use as:

x = [13 14 2 14 10 3 5 9 15 8];
y = myFilter(x, 3, @(x)min(x))

Note I am using CELLFUN in case fcn cannot operate across dimensions in a vectorized manner...

Community
  • 1
  • 1
Amro
  • 123,847
  • 25
  • 243
  • 454