Replace values in matrix based on condition and based on nearest X values

Hello,
I need to code a winsorized mean function for a 2d matrix.
The values needs to be changed based on a percentage.
I have two problems, the first is to understand how winsorized mean works in a 2d matrix (this is for an image).
And how can I change the values based on what I am explaining next (assuming that I understood how winsorized mean works).
My understanding of winsorized mean is, that I take the lowest and highest values and give them the value of the X amount of values closest to them.
So, if I have a matrix of 500x500, and the percentage of 10%, I need to give the value of the mean of the 50 nearest values.
An example:
I have a 20x20 matrix and I want to do the winsorized mean with 10%.
So I have to take all of those values in consideration?
10 12 45 82 96
47 54 69 23 33
78 27 .. 45 34
23 67 06 76 46
10 56 07 34 96
The ".." is the value I want to change.
and the result of that value would be: 45.
Thanks in advance.

Answers (1)

I've never heard of winsorized mean. What you describe sounds simply like the convolution:
inputMatrix = imread('cameraman.tif');
subplot(1, 2, 1);
imshow(inputMatrix, [])
[rows, columns] = size(inputMatrix);
percentage = 10;
windowWidth = round([rows * percentage / 100, columns * percentage / 100])
kernel = ones(windowWidth) / prod(windowWidth);
output = conv2(inputMatrix, kernel, 'same');
subplot(1, 2, 2);
imshow(output, [])
If you want the kernel to be a circle instead of a rectangle (so it's REALLY the N closest locations), you can use strel(). If you want the value to exclude the central window value when computing the mean, make the obvious changes.

4 Comments

What I found on winsorized mean is here: https://www.investopedia.com/terms/w/winsorized_mean.asp
I guess you probably have heard of trimmed mean. This one is a bit different because it removes elements, and winsorized mean changes them. (If I understood it correctly).
Now I found that instead of changing the lowest value based on the 10% closest values I have to change the 5% lowest values to their closest neighbour, and the same for the highest values.
Since this is for an image I think I have to use the mean of the surrounding values?
Convolution is a theoretical concept that has a basis in the physical real world. For example the point spread function of an imaging system is influenced by the convolution of the aperture stop with a plane wave. I don't know of any theoretical real world situation where the central pixel is ignored when computing the mean.
However that doesn't mean it can't be done. If you do a non-linear digital filter, you can do whatever you want regardless if it's something that happens in the real world. For example, the median filter is probably the best known digital non-linear filter. And there is no set of lenses that can perform a median filter on the image photons as they pass through the lens system.
There is a "sigma filter" that replaces central pixel values with the average of values that are within some factor times sigma (the standard deviation) of the mean. This is a non-linear denoising filter. So basically it "repairs" a pixel that is noisy by replacing it with the mean of pixels that are defined to be "not noisy".
Another filter you might like to know about is the bilateral filter.
And of course there are lots of denoising filters, some built in to MATLAB, such as non-local means, guided filter, BM3D, mean shift filter, etc.
So to include or exclude the central pixel really just depends on what you're trying to model. If you're modeling a real world system, like an optical imaging system, you'd include it. If you don't care about that and just want to exclude it because you think it will give you a better output image, you can do that too. In fact try it both ways and see which gives you a more pleasing image. There is no right or wrong answer (unless you're trying to simulate/model the physical world).
Just make your kernel then set the central pixel of it to zero. Then divide the kernel by the sum of the kernel values
kernel(midRow, midColumn) = 0;
kernel = sum(kernel) / nnz(kernel);

Sign in to comment.

Products

Release

R2021a

Asked:

on 31 Oct 2021

Commented:

on 31 Oct 2021

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!