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?
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.
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.
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 .
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.
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.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With