Set to zero values in matrix in between two lines

1 view (last 30 days)
Hello,
I would like to vectorize the following operation:
Given a 2D matrix/image and the slope and intercept of two lines (that don't cross each other within the matrix), I would like to put the values of the matrix (the pixels) in the band defined by the two lines to zero. I realize this is not clear but this exemple should illustrate well what I mean:
width=1000;
height=200;
A=rand(height,width); % create a random matrix/image
% slopes (s) and intersects (b) of two lines
s1=-0.1;
b1=130;
s2=-0.11;
b2=150;
% values of the matrix = 0 in between the two lines
for ii=1:width
for jj=floor(s1*ii+b1):floor(s2*ii+b2)
A(jj,ii)=0;
end
end
Then A looks like this (using imshow), where the boundaries of the dark triangle are the two lines define by s1,b1 and s2,b2
This works, but I didn't manage to vectorize this piece of code.
Thanks for the help.

Answers (4)

Voss
Voss on 14 Apr 2022
Edited: Voss on 14 Apr 2022
width=1000;
height=200;
A=rand(height,width); % create a random matrix/image
subplot(3,1,1);
imshow(A)
% slopes (s) and y-intercepts (b) of two lines
s1=-0.1;
b1=130;
s2=-0.11;
b2=150;
A1 = A; % make copies for comparison at the end
A2 = A;
% values of the matrix = 0 in between the two lines
% 1) vectorized method
[x,y] = meshgrid(1:width,1:height);
A1(floor(s1*x+b1) <= y & floor(s2*x+b2) >= y) = 0;
subplot(3,1,2);
imshow(A1)
% 2) original method
for ii=1:width
for jj=floor(s1*ii+b1):floor(s2*ii+b2)
A2(jj,ii)=0;
end
end
subplot(3,1,3)
imshow(A2)
% check that the two methods give the same result
isequal(A1,A2)
ans = logical
1
  2 Comments
Matt J
Matt J on 14 Apr 2022
Edited: Matt J on 14 Apr 2022
Speed things up a bit more by avoiding meshgrid() and floor().
[x,y] =deal(1:width,(1:height).');
A1(s1*x+b1 <= y & s2*x+b2 >= y) = 0;

Sign in to comment.


Scott MacKenzie
Scott MacKenzie on 14 Apr 2022
Edited: Scott MacKenzie on 14 Apr 2022
You can vectorize the inner loop:
% values of the matrix = 0 in between the two lines
for ii=1:width
A(floor(s1*ii+b1):floor(s2*ii+b2),ii) = 0;
end
Not sure if you can vectorize the entire sequence of assignments.
  1 Comment
p
p on 14 Apr 2022
Yes that makes sense, it speeds things up a bit, thanks

Sign in to comment.


p
p on 14 Apr 2022
Previous answers made me think of a way of doing this but using linear indices to limit the number of operations. What follow seems to be the fastest method so far.
ii=0:(width-1);
% id1 and id2 are the linear indices such that we want
% A(id1(1):id2(1))=0, ..., A(id1(end):id2(end))=0
id1 = floor(s1*ii+b1) + ii*height;
id2 = floor(s2*ii+b2) + ii*height;
% coloncatrld from https://blogs.mathworks.com/loren/2008/10/13/vectorizing-the-notion-of-colon/
% id=[id1(1):id2(1), ... , id1(end):id2(end)]
id=coloncatrld(id1, id2);
A(id)=0;

yanqi liu
yanqi liu on 15 Apr 2022
yes,sir,may be use mask to process,such as
width=1000;
height=200;
A=rand(height,width); % create a random matrix/image
figure; imshow(mat2gray(A));
% slopes (s) and intersects (b) of two lines
s1=-0.1;
b1=130;
s2=-0.11;
b2=150;
% vector
x = linspace(1, size(A, 2), 1e3);
y1 = s1*x + b1;
y2 = s2*x + b2;
pts = [x fliplr(x) x(1)
y1 fliplr(y2) y1(1)];
mk = roipoly(A,round(pts(1,:)), round(pts(2,:)));
A(mk) = 0;
figure; imshow(mat2gray(A));

Categories

Find more on Creating and Concatenating Matrices in Help Center and File Exchange

Products


Release

R2019b

Community Treasure Hunt

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

Start Hunting!