Set to zero values in matrix in between two lines

12 次查看(过去 30 天)
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.

回答(4 个)

Voss
Voss 2022-4-14
编辑:Voss 2022-4-14
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 个评论
Stephane
Stephane 2022-4-14
Thank you!
This is slower than the previous answer with a single for loop, but I think this makes sense given that with this method you do more calculations on matrices. But still this made me think of a way of doing it faster (see my answer below) using linear indices, so thanks!
Matt J
Matt J 2022-4-14
编辑:Matt J 2022-4-14
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;

请先登录,再进行评论。


Scott MacKenzie
Scott MacKenzie 2022-4-14
编辑:Scott MacKenzie 2022-4-14
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.

Stephane
Stephane 2022-4-14
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 2022-4-15
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));

类别

Help CenterFile Exchange 中查找有关 Array and Matrix Mathematics 的更多信息

产品


版本

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by