adaptive sliding window filter - matlab

I want to create an adaptive sliding window filter that operates on a sparse matrix (Image). I want to calculate an average of all pixels with non-zero values within a 9x9 window for each objective pixel with non zero value. I tried to do it using the following code
fun = #(x) mean(x(x~=0));
B = nlfilter(A,[9 9],fun);
A is the sparse image to be filtered. The code runs but returns a non zero value for elements that have a zero pixel value in the unfiltered sparse image. I also want to make sure that to calculate the average for an objective pixel, a minimum of 5 non-zero samples are present within the window. If this is not possible, I want to keep expanding the sliding window until this is fulfilled.
Any suggestions are greatly appreciated.

Related

MATLAB: How to slide a window over a matrix without padding?

I'll illustrate my problem on an example
I have a 3x100 matrix and I want to slide a 3x3 filter over it.
However, I do not want any of the padding that imfilter would use, such as X, symmetric, replicate, etc., which would yield a 3x100 output.
I rather want the sliding window to be only applied when there is real data, such that my output would be 1x (100 - 4).
What would be the most elegant (loopless) way to do this in matlab?
You can use the built-in conv2 function with 'Valid' as the shape parameter which will only provide results when there is a complete overlap between the filter and the data.
filtered = conv2(data, filter, 'valid');

Explaining corr2 function in Matlab

Can someone explain to me the correlation function corr2 in MATLAB? I know that it is for 2D comparing similarities of objects, but in the equation I have doubts what it is A and B (probably matrices for comparison), and also Amn and Bmn.
I'm not sure how MATLAB executes this function, because I have found in several cases that the correlation is not executed for the entire image (matrix) but instead it divides the image into blocks and then compares blocks of one picture with blocks of another picture.
In MATLAB's documentation, the corr2 equation is not put as referral point to the way the equation itself is calculated, like in other functions in MATLAB's documentation, such as referring to what book it is taken from and where it is explained.
The correlation coefficient is a number representing the similarity between 2 images in relation with their respective pixel intensity.
As you pointed out this function is used to calculate this coefficient:
Here A and B are the images you are comparing, whereas the subscript indices m and n refer to the pixel location in the image. Basically what Matab does is to compute, for every pixel location in both images, the difference between the intensity value at that pixel and the mean intensity of the whole image, denoted as a letter with a straightline over it.
As Kostya pointed out, typing edit corr2 in the command window will show you the code used by Matlab to compute the correlation coefficient. The formula is basically this:
a = a - mean2(a);
b = b - mean2(b);
r = sum(sum(a.*b))/sqrt(sum(sum(a.*a))*sum(sum(b.*b)));
where:
a is the input image and b is the image you wish to compare to a.
If we break down the formula, we see that a - mean2(a) and b-mean2(b) are the elements in the numerator of the above equation. mean2(a) is equivalent to mean(mean(a)) or mean(a(:)), that is the mean intensity of the whole image. This is only calculated once.
The 3rd line of code calculates the coefficient. Here sum(sum(a.*b)) calculates the double-sum present in the formula element-wise, that is considering each pixel location separately. Be aware that using sum(a) calculates the sum in every column individually, hence in order to get a single value you need to apply sum twice.
That's pretty much the same happening in the denominator, however calculations are performed on a-mean2(a)^2 and b-mean2(b)^2. You can see this a some kind of normalization process in which you consider the pixel intensity difference among each individual image.
As for your last comment, you can break down an image into small blocks and calculate the correlation coefficient on them; that might save some time for very large images but since everything is vectorized the calculation is quite fast. It might be useful in distributed processing I guess. Of course the correlation coefficient between 2 blocks of images is not necessarily identical to that of the whole image.
For the sake of curiosity you can look at this paper which highlights some caveats in using the correlation coefficient for image comparison.
Hope that makes things a bit clearer!

How can I fasten the "histc" Matlab function

I need to fasten this part of my Matlab code :
double(sum(histc(windows, 0:1:255),2)')
It is applied on every pixel of a large image, it is for calculating the local histogram (within 'windows') so it is very quite consuming.
Do you have any suggestion to fasten the computing ?
Thanks a lot.
You can exploit the overlap between adjacent pixels. Lets say you us a window of size 3x3 and have calculated the histogram for a pixel I(x,y), then the histogram for pixel I(x+1,y) will contain 6 of the same pixels. So you need only subtract 3 values and add 3.
Your code looks wrong. histc returns bin counts and then you sum the counts which should always add up to the size of your window. Do you want to calculate the sum of pixel intensities within the window? Then you should just use the sum function directly.

Conv2 function values goes above 255 when convolving an image and a window?

I have a window of size 5*5.An image of size 360*300.When i convolve the two using the function.I am working on matlab.
conv2(image,window,'same');
the values of the pixel goes above 255.I used the code below to restrict the value below 255.
( conv2(image,window,'same')/sum(sum(window));
I have 3 questions which are listed below.
Is it the right way to proceed??
Does the function take care of this constraint also?
Any alternate method?
To specify what is said in the comments:
The overall sum of your window
ws = sum(window(:))
is like an amplification. If ws>1, then your image tends to get brighter. If 0 < ws < 1 your image will get darker. If ws = 0, then you will receive an image, that will average at about zero. This is often the case in edge detection scenarios. For example, the Sobel Operator has a sum of zero.
Often, the convolution is executed with an amplification equal to 1, to separate the amplification from the convolution. As convolution is a linear operator, it does not matter whether you divide the window by ws or the resulting image.
To answer questions 1 and 3 in particular: The usual way is to normalize the window. That is:
window = window ./ sum(window(:)); % Normalize convolution kernel
conv2(image,window,'same');

Determine the position and value of peak

I have a graph with five major peaks. I'd like to find the position and value of the first peak (the one furthest to the right). I have more than 100 different plots of this and the peak grows and shrinks in size in the various plots, and will need to use a for loop. I'm just stuck on determining the x and y values to a large number of significant figures using Matlab code.
Here's one of the many plots:
If you know for sure you're always gonna have 5 peaks I think the FileExchange function extrema will be very helpful, see here.
This will return you the maxima (and minima if needed) in descending order, so the first elements of output zmax and imax are respectively the maximal value and its index, their second elements are the second maximum value and its index and so on.
In the case if the peak you need is always the smallest of the five you'll just need zmax(5) and imax(5) to determine the 5th biggest maximum.
If you have access to Signal Processing Toolbox, findpeaks is the function you are looking for. It can be invoked using different options including number of peaks, which can be helpful when that information is available.