I have an image 640x480 img
, and I want to replace pixels having values not in this list or array x=[1, 2, 3, 4, 5]
with a certain value 10
, so that any pixel in img
which doesn't have the any of the values in x
will be replaced with 10
. I already know how to replace only one value using img(img~=1)=10
or multiple values using this img(img~=1 & img~=2 & img~=3 & img~=4 & img~=5)=10
but I when I tried this img(img~=x)=10
it gave an error saying Matrix dimensions must agree
. So if anyone could please advise.
You can achieve this very easily with a combination of permute
and bsxfun
. We can create a 3D column vector that consists of the elements of [1,2,3,4,5]
, then use bsxfun
with the not equals method (@ne
) on your image (assuming grayscale) so that we thus create a 3D matrix of 5 slices. Each slice would tell you whether the locations in the image do not match an element in x
. The first slice would give you the locations that don't match x = 1
, the second slice would give you the locations that don't match x = 2
, and so on.
Once you finish this, we can use an all
call operating on the third dimension to consolidate the pixel locations that are not equal to all of 1, 2, 3, 4 or 5. The last step would be to take this logical
map, which that tells you the locations that are none of 1, 2, 3, 4, or 5 and we'd set those locations to 10.
One thing we need to consider is that the image type and the vector x
must be the same type. We can ensure this by casting the vector to be the same class as img
.
As such, do something like this:
x = permute([1 2 3 4 5], [3 1 2]);
vals = bsxfun(@ne, img, cast(x, class(img)));
ind = all(vals, 3);
img(ind) = 10;
The advantage of the above method is that the list you want to use to check for the elements can be whatever you want. It prevents having messy logical indexing syntax, like img(img ~= 1 & img ~= 2 & ....)
. All you have to do is change the input list at the beginning line of the code, and bsxfun
, permute
and any
should do the work for you.
Here's an example 5 x 5 image:
>> rng(123123);
>> img = randi(7, 5, 5)
img =
3 4 3 6 5
7 2 6 5 1
3 1 6 1 7
6 4 4 3 3
6 2 4 1 3
By using the code above, the output we get is:
img =
3 4 3 10 5
10 2 10 5 1
3 1 10 1 10
10 4 4 3 3
10 2 4 1 3
You can most certainly see that those elements that are neither 1, 2, 3, 4 or 5 get set to 10.
If you don't like the permute
and bsxfun
approach, one way would be to have a for
loop and with an initially all true
array, keep logical ANDing the final result with a logical
map that consists of those locations which are not equal to each value in x
. In the end, we will have a logical map where true
are those locations that are neither equal to 1, 2, 3, 4 or 5.
Therefore, do something like this:
ind = true(size(img));
for idx = 1 : 5
ind = ind & img ~= idx;
end
img(ind) = 10;
If you do this instead, you'll see that we get the same answer.
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