# mask a matrix based on values in two arrays

59 views (last 30 days)

Show older comments

I am looking for a more effective means of masking a matrix based on values held in two arrays. Ultimately I'm looking to mask off chunks of a surface to alter their values. I have been able to achieve this based on the logic in the following loop, but for my actual model runs, which typically have meshgrid sizes in the millions of elements, and array lengths in the 1000's I feel like there could be a less memory intensive (and read/write intensive) solution.

[x y]=meshgrid(0:1:100,0:1:100);

u=floor(rand(10,1)*100);

v=floor(rand(10,1)*100);

padu=5; padv=5;

for i=1:size(u,1)

if i==1

mask=1*(x>u(i)-padu & x<u(i)+padu & y>v(i)-padv & y<v(i)+padv);

else

maskh=(x>u(i)-padu & x<u(i)+padu & y>v(i)-padv & y<v(i)+padv);

mask(maskh==1)=1;

end

end

surf(x,y,mask)

is there a more effective solution? I've searched but perhaps using the wrong terms, as I don't have an answer.

Thank you.

##### 2 Comments

Jan
on 19 Nov 2022

### Accepted Answer

Jan
on 19 Nov 2022

Edited: Jan
on 19 Nov 2022

n = 1e4;

u = floor(rand(10,1)*100);

v = floor(rand(10,1)*100);

tic % Original version:

[x y] = meshgrid(linspace(0, 100, n), linspace(0, 100, n));

padu = 5;

padv = 5;

for i=1:size(u,1)

if i==1

mask=1*(x>u(i)-padu & x<u(i)+padu & y>v(i)-padv & y<v(i)+padv);

else

maskh=(x>u(i)-padu & x<u(i)+padu & y>v(i)-padv & y<v(i)+padv);

mask(maskh==1)=1;

end

end

toc

tic; % Version 1:

x = linspace(0, 100, n); % Avoid MESHGRID, because if creates huge

y = linspace(0, 100, n).'; % redundant matrices

padu = 5;

padv = 5;

% Use a logical array as mask instead of a double array:

mask2 = (x>u(1)-padu & x<u(1)+padu) & (y>v(1)-padv & y<v(1)+padv);

on = true; % Slightly faster to use a constant instead of a function

for i = 2:size(u,1)

% Avoid check of i==1 in each iteration my moving this exception

% out of the loop.

maskh = (x>u(i)-padu & x<u(i)+padu) & (y>v(i)-padv & y<v(i)+padv);

mask2(maskh) = on;

end

toc

assert(isequal(mask, mask2), 'Different results!')

It is faster to call

mask = or(mask, newmask)

then

newmask = xy;

mask(newmask) = true;

See:

tic; % Version 2

x = linspace(0, 100, n).';

y = linspace(0, 100, n).';

padu = 5;

padv = 5;

xm = (x > u.'-padu & x < u.' + padu); % Or: abs(x - u.') < padu;

ym = (y > v.'-padv & y < v.' + padv); % Or: abs(y - v.') < padv;

on = true;

mask3 = false(n, n);

for i = 1:size(u, 1)

mask3 = mask3 | (xm(:, i).' & ym(:, i));

end

toc

assert(isequal(mask, mask3), 'Different results!')

In my measurements this has almost the same speed:

tic; % Version 3

x = linspace(0, 100, n); % Avoid MESHGRID, because if creates huge

y = linspace(0, 100, n).'; % redundant matrices

padu = 5;

padv = 5;

mask4 = false;

for i = 1:size(u,1)

mask4 = mask4 | (abs(x-u(i)) < padu) & (abs(y-v(i)) < padv);

% Or:

% mask4 = mask4 | (x>u(i)-padu & x<u(i)+padu) & (y>v(i)-padv & y<v(i)+padv);

end

toc

assert(isequal(mask, mask4), 'Different results!')

Check the speed with the original data on your local machine. The timings from the forum seem to be strange sometimes.

### More Answers (1)

Catalytic
on 20 Nov 2022

A=accumarray([u,v],1,[100,100]);

k=ones(2*padu,2*padv);

mask=conv2(A,k,'same');

##### 0 Comments

### See Also

### Categories

### Community Treasure Hunt

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

Start Hunting!