フィルターのクリア

Set to zero values in matrix in between two lines

1 回表示 (過去 30 日間)
Stephane
Stephane 2022 年 4 月 14 日
回答済み: yanqi liu 2022 年 4 月 15 日
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.
  1 件のコメント
Stephane
Stephane 2022 年 4 月 14 日
Yes that makes sense, it speeds things up a bit, thanks

サインインしてコメントする。


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 Center および File ExchangeLogical についてさらに検索

製品


リリース

R2019b

Community Treasure Hunt

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

Start Hunting!

Translated by