0

I would like to iterate over an image in a pixel-by-pixel fashion using a sliding window of size 3x3 pixels, and at each position of the sliding window I want to calculate the minimum, maximum, mean, and standard deviation of the pixel values.

Can you please tell me how to accomplish this? Also, what is the fastest way to perform this operation?

Many thanks in advance!

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
  • Please show what you have already tried, including functions that you considered using, approaches you considered to take, implementations in other languages, etc. If there's something unclear about the MATLAB documentation - you should mention that. If you're running into some errors - you should mention that. If you are worried about performance problems - you should ask about that (i.e. "_I did X, could you suggest a more efficient way?_"). Showing some effort to solve one's problem on one's own encourages others to answer. Good luck! – Dev-iL Nov 19 '16 at 10:35

1 Answers1

2

You should always use inbuilt functions when possible.

nlfilter is recommended for sliding window operations. colfilt is the same but with usually better memory locality, you should use it.

neigh = [3,3];

I_mean = colfilt(I, neigh, 'sliding', @mean);
I_max = colfilt(I, neigh, 'sliding', @max);
I_min = colfilt(I, neigh, 'sliding', @min);

Standard deviation can be calculated using stdfilt. colfilt(... @std) requires a datatype conversion for some reason, and is ~4x slower on my machine.

I_std = stdfilt(I); 

Returns a standard deviation image made with a 3x3 sliding window.

If by fair comparison you mean comparing speed, note that colfilt and stdfilt are quite different.

I_std = colfilt(double(I), neigh, 'sliding', @std);

You can also calculate the mean image via imfilter. It's an order of magnitude faster, but the border pixel output is a bit different

tic;
meanh = fspecial('average', neigh);
I_mean = imfilter(I, meanh);
toc

Elapsed time is 0.024311 seconds.

vs.

tic;
I_mean2 = colfilt(I, neigh, 'sliding', @mean);
toc

Elapsed time is 0.649545 seconds.

Here's a illustration of the difference (double(I_mean)-double(I_mean2)). Only the border pixels differ:

Image of differences

The speed difference grows larger and larger the bigger the neighbourhood is.

Dev-iL
  • 23,742
  • 7
  • 57
  • 99
Tapio
  • 1,502
  • 1
  • 12
  • 24
  • Many thanks for your help. In fact, the time complexity is what I am trying to measure. My original code is in Java, which scans the image only once. During the scan, the four values, i.e., min, max, mean and stdev, for the current position of the sliding window are calculated and fed into a function before proceeding to the next position. In your code, I think four images (matrices) will be generated, and then I need to re-scan those images in order to operate on each position of the window. Any idea on how to mimic my java procedure? Your hep is appreciated. – It's me again Nov 19 '16 at 10:17
  • Sorry but I don't understand what you are trying to achieve. Matlab is all about vectorized code and calling highly optimized routines. If you implement something with for-loops and try to compare the speed with a similiar routine in Java it's comparing apples to oranges. If it's your function waiting for the images to be calculated you are worried about I can guarantee that this way is faster. You can just loop over the images afterwards. Or even better, feed them to a vectorized function. – Tapio Nov 19 '16 at 10:43