Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set matrix element to mean of surrounding elements?

I have a matrix X that represents an image that was affected by noise. I also have a boolean matrix M that represents which pixels were affected by noise. What I want to do is to set every 'corrupted' pixel to the mean of its eight neighboring pixels.

Corrupted pixels are guaranteed to always be surrounded by uncorrupted ones, and also none of the pixels on the borders of the image are corrupted. What function can I used to write a vectorised version of this?

like image 461
Paul Manta Avatar asked Mar 23 '13 11:03

Paul Manta


People also ask

How do you find the average of all values in a matrix in MATLAB?

M = mean( A , 'all' ) computes the mean over all elements of A . This syntax is valid for MATLAB® versions R2018b and later. M = mean( A , dim ) returns the mean along dimension dim . For example, if A is a matrix, then mean(A,2) is a column vector containing the mean of each row.

How do you compare elements in a matrix in MATLAB?

One of the ways to do this is to create a matrix C containing the maximum of A and B (element by element) and then checking if this new matrix is same as A or not.

How do you reference an element in a matrix?

The most common way is to explicitly specify the indices of the elements. For example, to access a single element of a matrix, specify the row number followed by the column number of the element. e is the element in the 3,2 position (third row, second column) of A .

How do you find the value of an element in a matrix?

The number of elements of a matrix = the number of rows multiplied by the number of columns. For example, if the number of rows is 3 and the number of columns is 4 in a matrix then the number of elements in it is 3 x 4 = 12.


2 Answers

For your situation, this should perform quite fast

fixed = conv2 (image, [1 1 1; 1 0 1; 1 1 1]/8, "same")
# mask is a logical matrix for the corrupted pixels
image(mask) = fixed(mask)

Explanation: a mean filter is done with the conv2 function. To calculate the average of a pixel and its neighbors, the kernel used is ones (3) / 9 which means that 1/9 of each pixel value is used to calculate the new value. Since you don't want to count the center pixel in the average, you make its value 0 (in the kernel), and the others to 1/8.

like image 181
carandraug Avatar answered Oct 11 '22 05:10

carandraug


This is probably not the most effective solution, but it should work.

N = size(M, 1);
target_ind = find(M);
offset = [-N-1, -N, -N+1, -1, 0, 1, N-1, N, N+1];

area_ind = bsxfun(@plus, offset, target_ind);
X(target_ind) = median(X(area_ind), 2);

Since all corrupted pixels are guaranteed to be surrounded by pixels, we can rather easily compute the linear indices of each corrupted pixel's neighbors. Here I've assumed that X is a grayscale image.

If I has more than one channel, then we could loop over each channel and add an offset to target_ind and area_ind each time:

for i = 1:size(X, 3)
    chan_offset = (i - 1)*size(X, 1)*size(X, 2) % Add the number of elements in previous channels to get indices in the current channel
    X(target_ind + chan_offset) = median(X(area_ind + chan_offset), 2);
end
like image 44
Bjoern H Avatar answered Oct 11 '22 04:10

Bjoern H