创建单边距离图
Create a one-sided distance map
我用这段代码创建了一个由零组成的黑色正方形,中间有一条由 1 组成的白色垂直线,我想创建一个关于这条线的距离图,但只在垂直线的左侧。我怎样才能做到这一点?
以下代码生成直线两侧的距离图。
c=zeros(500,500);
c(:,250)=1;
figure, imshow(c)
[D, idx]= bwdist(c,'euclidean')
您可以计算整个图像的距离图,然后将您不感兴趣的一侧置零(或将值设置为 NaN
)
D = bwdist(c, 'euclidean');
D(:,251:end) = NaN;
一种更稳健的方法(无需对任何列进行硬编码)是在调用 bwdist
之前修改 c
,方法是将行右侧的任何内容设置为 1
,以便每个像素的结果距离是 0
。您可以通过计算各行的累计和来做到这一点
D = bwdist(cumsum(c, 2) > 0, 'euclidean');
实际上,这个问题可以用不同的、具有挑战性的方式提出。如果我有不同的输入形状(不是单列线),如果我想找到特定角度间隔(不仅仅是左侧)的距离图怎么办?这是我的解决方案。找到输入形状的 (x,y) 坐标,然后为每个像素找到特定方向 + 方向间隔的掩码。这是函数。
function mask = directional_mask(im, mainDirection, dirInterval)
% im: BW input image
% mainDirection : mask direction (in degrees)
% dirInterval: mask direction interval (from dirMask-dirInterval to dirMask+dirInterval)
[Ys, Xs] = find(im);
[sizeX, sizeY] = size(im);
[X, Y] = meshgrid(1:sizeX,1:sizeY);
mask = im * 0;
for i = 1 : numel(Xs)
refX = Xs(i);
refY = Ys(i);
[theta, ~] = cart2pol(X-refX, Y-refY);
% adding pi/2 so that north angle is 0 degree
dirmat = wrapTo2Pi(theta + pi/2);
dirmat = rad2deg(dirmat);
% upper and lower direction intervals
thetaUp = mainDirection + dirInterval;
thetaDown = mainDirection - dirInterval;
dirmat2 = dirmat(:);
% finding indices of the angle intervals
thetas = [thetaUp, thetaDown];
if thetaUp >= 360
thetaUp = thetas(1) - 360;
thetaDown = thetas(2);
dirmat2((dirmat2>thetaUp) & (dirmat2<thetaDown)) = nan;
elseif thetaDown < 0
thetaUp = thetas(1);
thetaDown = thetas(2) + 360;
dirmat2((dirmat2>thetaUp) & (dirmat2<thetaDown)) = nan;
else
dirmat2((dirmat2>thetaUp) | (dirmat2<thetaDown)) = nan;
end
% final mask
tmp = im*0;
tmp(~isnan(dirmat2)) = 1;
mask = mask | tmp;
end
mask = double(mask);
然后假设我有一张如下图所示的输入图像,我想计算朝向 45 度的距离图。
im=zeros(100);
for i=35:65; im(i,i)=1; end
im2=imrotate(im,60); im=imresize(im2,size(im)); im=im~=0;
mainDirection = 45;
dirInterval = 5;
[mask] = directional_mask(im, mainDirection, dirInterval);
% original distance map
d = bwdist(im);
% directional distance map
d2 = mask.*d;
figure;
subplot(131); imagesc(mask+2*im), axis image; colorbar; title('Mask + Orig. Input')
subplot(132); imagesc(d), axis image; colorbar; title('Initial Distance Map')
subplot(133); imagesc(d2), axis image; colorbar; title('Directional Distance Map')
set(findall(gcf,'-property','FontSize'),'FontSize',16)
假设我想要 180 度的距离贴图。只需更改 "mainDirection"
mainDirection = 180;
让我们尝试不同的形状。
im=zeros(100);
im(40:60,40:60)=1; im2=imrotate(im,30);im=imresize(im2,size(im)); im=im~=0;
mainDirection = 180;
dirInterval = 5;
如果你想要一个特定方向间隔(theta+-间隔)的掩码,只需更改"dirInterval"。这是一个例子
mainDirection = 180;
dirInterval = 30;
在最初的问题中,@Mac 想要将距离图向左侧屏蔽。那么:
im=zeros(100); im(:,50)=1;
mainDirection = 270;
dirInterval = 90;
我用这段代码创建了一个由零组成的黑色正方形,中间有一条由 1 组成的白色垂直线,我想创建一个关于这条线的距离图,但只在垂直线的左侧。我怎样才能做到这一点?
以下代码生成直线两侧的距离图。
c=zeros(500,500);
c(:,250)=1;
figure, imshow(c)
[D, idx]= bwdist(c,'euclidean')
您可以计算整个图像的距离图,然后将您不感兴趣的一侧置零(或将值设置为 NaN
)
D = bwdist(c, 'euclidean');
D(:,251:end) = NaN;
一种更稳健的方法(无需对任何列进行硬编码)是在调用 bwdist
之前修改 c
,方法是将行右侧的任何内容设置为 1
,以便每个像素的结果距离是 0
。您可以通过计算各行的累计和来做到这一点
D = bwdist(cumsum(c, 2) > 0, 'euclidean');
实际上,这个问题可以用不同的、具有挑战性的方式提出。如果我有不同的输入形状(不是单列线),如果我想找到特定角度间隔(不仅仅是左侧)的距离图怎么办?这是我的解决方案。找到输入形状的 (x,y) 坐标,然后为每个像素找到特定方向 + 方向间隔的掩码。这是函数。
function mask = directional_mask(im, mainDirection, dirInterval)
% im: BW input image
% mainDirection : mask direction (in degrees)
% dirInterval: mask direction interval (from dirMask-dirInterval to dirMask+dirInterval)
[Ys, Xs] = find(im);
[sizeX, sizeY] = size(im);
[X, Y] = meshgrid(1:sizeX,1:sizeY);
mask = im * 0;
for i = 1 : numel(Xs)
refX = Xs(i);
refY = Ys(i);
[theta, ~] = cart2pol(X-refX, Y-refY);
% adding pi/2 so that north angle is 0 degree
dirmat = wrapTo2Pi(theta + pi/2);
dirmat = rad2deg(dirmat);
% upper and lower direction intervals
thetaUp = mainDirection + dirInterval;
thetaDown = mainDirection - dirInterval;
dirmat2 = dirmat(:);
% finding indices of the angle intervals
thetas = [thetaUp, thetaDown];
if thetaUp >= 360
thetaUp = thetas(1) - 360;
thetaDown = thetas(2);
dirmat2((dirmat2>thetaUp) & (dirmat2<thetaDown)) = nan;
elseif thetaDown < 0
thetaUp = thetas(1);
thetaDown = thetas(2) + 360;
dirmat2((dirmat2>thetaUp) & (dirmat2<thetaDown)) = nan;
else
dirmat2((dirmat2>thetaUp) | (dirmat2<thetaDown)) = nan;
end
% final mask
tmp = im*0;
tmp(~isnan(dirmat2)) = 1;
mask = mask | tmp;
end
mask = double(mask);
然后假设我有一张如下图所示的输入图像,我想计算朝向 45 度的距离图。
im=zeros(100);
for i=35:65; im(i,i)=1; end
im2=imrotate(im,60); im=imresize(im2,size(im)); im=im~=0;
mainDirection = 45;
dirInterval = 5;
[mask] = directional_mask(im, mainDirection, dirInterval);
% original distance map
d = bwdist(im);
% directional distance map
d2 = mask.*d;
figure;
subplot(131); imagesc(mask+2*im), axis image; colorbar; title('Mask + Orig. Input')
subplot(132); imagesc(d), axis image; colorbar; title('Initial Distance Map')
subplot(133); imagesc(d2), axis image; colorbar; title('Directional Distance Map')
set(findall(gcf,'-property','FontSize'),'FontSize',16)
假设我想要 180 度的距离贴图。只需更改 "mainDirection"
mainDirection = 180;
让我们尝试不同的形状。
im=zeros(100);
im(40:60,40:60)=1; im2=imrotate(im,30);im=imresize(im2,size(im)); im=im~=0;
mainDirection = 180;
dirInterval = 5;
如果你想要一个特定方向间隔(theta+-间隔)的掩码,只需更改"dirInterval"。这是一个例子
mainDirection = 180;
dirInterval = 30;
在最初的问题中,@Mac 想要将距离图向左侧屏蔽。那么:
im=zeros(100); im(:,50)=1;
mainDirection = 270;
dirInterval = 90;