【问题标题】:Chain code infinite loop链码无限循环
【发布时间】:2012-10-16 04:16:32
【问题描述】:

我正在实现链码,但偶然发现了一个小问题。首先我做什么:

我从边界上的某个像素开始,然后检查与此相关的相邻像素:

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

在这张图片上:

如果您想自己尝试一下

编辑:

正如 cmets 中所建议的,在我的第二个版本中,我确保算法没有使用以前访问过的像素。结果:

如您所见,这不是一个有效的答案。

编辑 2

关于@jonas 的更新解决方案。我很快把它放在excel中,这样更容易理解。 (尚未找到带 1 的像素,已找到像素 x)。

所以这不是 100% 工作的,在处理庞大的数据集时,确保每张图片的边缘都是 2 像素宽是相当不可能的。

【问题讨论】:

  • 也许标记访问过的节点并且从不访问它们两次?某事。在深度优先搜索的行中。你尽可能深入,然后退后一步,走另一条合理的道路。

标签: matlab image-processing


【解决方案1】:

您的算法的问题在于,它只检查要访问的“候选”像素是否是对象的一部分——但没有执行额外的检查来确保像素是边界的一部分。这就是为什么它会愉快地穿过对象的内部。

一种流行的边界追踪算法是摩尔邻域追踪算法。除了Wikipedia page,看看this page,它更详细地解释了算法背后的思想。

【讨论】:

    【解决方案2】:

    解决此问题的最简单方法是使用函数BWTRACEBOUNDARY

    (x,y) 为起点,您可以这样写:

    B = bwtraceboundary(Ibw,[x,y],'N');
    

    绘制在图像上的结果如下所示:

    编辑

    如果你不能使用bwtraceboundary,你应该先只获取边界像素:

    边界 = Ibw - imerode(Ibw,ones(3));

    只要您的对象宽于两个像素,这将避免几乎所有问题。

    【讨论】:

    • 刚刚注意到我从北而不是东开始。我认为这不重要。
    • 我不能用这个。我正在尝试快速制作算法原型,以便查看它是否适用于我的图像。然后我想在java中实现它。有了这个,我不知道它是如何工作的,或者我的版本有什么问题
    • 感谢更新,但正如您所说,当它的宽度超过 2 个像素时仍然存在问题。为了让其他人理解这一点,我将问题添加到edit2下的问题中。
    猜你喜欢
    • 1970-01-01
    • 2018-04-10
    • 1970-01-01
    • 1970-01-01
    • 2012-05-01
    • 1970-01-01
    • 2013-03-19
    • 2018-04-04
    • 1970-01-01
    相关资源
    最近更新 更多