我正在实施链码,我偶然发现了一个小问题。首先我做的是:
我从我的边界上的某个像素开始,然后检查哪个相邻像素存在于此处:
3 2 1
\ | /
4-- --0
/ | \
5 6 7
虽然我有一个问题:
小红点是算法启动的地方。然后第一个方向是2然后是1然后是0然后是0 ......
如果你按照黄点,你会看到它以两个点相邻的方式结束。这是算法进入方向4的地方(因为在方向0,1,2或3处没有值为1的像素)。虽然在下一步它检查方向0(这始终是第一个开始的方向)......当然它存在,因为它是前一个点并且将向右移动。在这里,它被卡在一个无限循环中(从左到右,从右到左)。
我现在的问题是,如何解决这个问题?
我使用的代码是:
% Implementation of tangent angle function (chain code)
clear
clc
directions = [ 1, 0
1,-1
0,-1
-1,-1
-1, 0
-1, 1
0, 1
1, 1]
I = imread('./IMAGES/1/M_201005_1_0001.pgm');
Ibw = im2bw(I,0.15); % This is also by setting all the pixels with intesity lower than 17 to 0;
tanAngFunc ={};
[row,col] = find(Ibw);
y = col(find(max(row)==row))
x = max(row)
imshow(I)
hold on;
plot(y,x,'r.','MarkerSize',1)
hold on
l=1;
not_done = true;
while not_done
if l== 36
'test'
end
% Right (0)
if Ibw(x+directions(1,2),y+directions(1,1)) ~=0
tanAngFunc{l} = 0;
x= x+directions(1,2);
y= y+directions(1,1);
% Above right(1)
elseif Ibw(x+directions(2,2),y+directions(2,1)) ~=0
tanAngFunc{l} = 2;
x= x+directions(2,2);
y= y+directions(2,1);
% Above (2)
elseif Ibw(x+directions(3,2),y+directions(3,1)) ~=0
tanAngFunc{l} = 2;
x= x+directions(3,2);
y= y+directions(3,1);
% Above left (3)
elseif Ibw(x+directions(4,2),y+directions(4,1)) ~=0
tanAngFunc{l} = 2;
x= x+directions(4,2);
y= y+directions(4,1);
% Left (4)
elseif Ibw(x+directions(5,2),y+directions(5,1)) ~=0
tanAngFunc{l} = 2;
x= x+directions(5,2);
y= y+directions(5,1);
% Bottom left (5)
elseif Ibw(x+directions(6,2),y+directions(6,1)) ~=0
tanAngFunc{l} = 2;
x= x+directions(6,2);
y= y+directions(6,1);
% Bottom (6)
elseif Ibw(x+directions(7,2),y+directions(7,1)) ~=0
tanAngFunc{l} = 2;
x= x+directions(7,2);
y= y+directions(7,1);
% Bottom right (7)
elseif Ibw(x+directions(8,2),y+directions(8,1)) ~=0
tanAngFunc{l} = 3;
x= x+directions(8,2);
y= y+directions(8,1);
end
plot(y,x,'y.','MarkerSize',3)
hold on
pause(1)
l = l + 1;
not_done = (x ~= col(find(max(row)==row)) && y ~= max(row));
end
在此图片上:
如果你想自己试试
修改
正如评论中所建议的那样,在我的第二个版本中,我确保算法没有使用以前访问过的像素。结果:
正如您所看到的,这不是一个有效的答案。
修改2
关于@jonas的更新解决方案。我很快把它放在Excel中,所以它更容易理解。 (尚未找到带有1的像素,已找到像素x)。
所以这不能100%工作,在使用庞大的数据集时,确保每张图片的边缘宽2像素是不可能的。
答案 0 :(得分:2)
您的算法存在的问题是它只检查"候选者"要访问的像素是对象的一部分 - 但不执行其他检查以确保像素是边界的一部分。这就是为什么它会愉快地穿过对象的内部。
一种流行的边界追踪算法是摩尔邻域追踪算法。除了Wikipedia page之外,请查看this page,它会更详细地解释算法背后的想法。
答案 1 :(得分:1)
解决此问题的最简单方法是使用函数BWTRACEBOUNDARY。
用你的起点(x,y)
,你会写:
B = bwtraceboundary(Ibw,[x,y],'N');
,在图像上绘制的结果如下所示:
修改强>
如果您无法使用bwtraceboundary
,则应首先获取边界像素:
boundary = Ibw - imerode(Ibw,(3));
只要您的对象宽于两个像素,这将避免几乎所有问题。