2014-12-07 166 views
1

我有一个图像,我想将它转换为逻辑图像,包括线条是黑色和背景是白色的。当然,使用阈值方法可以做到这一点,但我不想这样做。我想通过使用线跟踪方法或类似的方法来检测它。用MATLAB跟踪线条

这是关于视网膜血管检测。我找到了article,但我不知道创建动态搜索窗口的方式。

我该怎么做?

原图:enter image description here

跟踪方式: enter image description here

我准备的图像与油漆。

+0

你到目前为止尝试过什么?你有没有研究过可以做到这一点的方法? – eigenchris 2014-12-07 15:57:29

+0

为什么你要使用这样的线追踪方法?我觉得这可能是一个更大的问题的一部分,你应该分享 – Sean 2014-12-07 17:04:09

+0

@eigenchris我编辑我的问题 – ffttyy 2014-12-07 17:11:56

回答

5

这是一个经典的Breadth First Search (BFS)问题。您可以将您的示例中标出的起点视为进入迷宫的入口点,您的工作就是找到迷宫的出路。 BFS背后的基本推动力是它使用了queue。在起点上,你将这一点加入队列。然后,当队列不是空,出列点从队列,然后检查其任何邻国,看看如果您有:

  1. 之前没有访问过他们。
  2. 如果它们是迷宫中的路径的点....或者在这种情况下,这些是在该线内的船只点。

如果您有任何满足(1)和(2)的要点,可以通过排队将这些点加入到队列中。一旦完成将点添加到队列中,您将返回并使另一个点出列并重复该算法,直到您的队列为空。


为了您的线跟踪算法,你会做什么是对你已经离队的每一点,你会标记在彩色图像...让我们说你会以红色标记这一点。一旦你将这个点出列,将那些你没有访问过的点和那些有效的船只点加入你的队列中,然后返回并将另一个点出列,然后重复这个逻辑。你会继续这个,直到你的队列为空。关于BFS的好处是,它允许您同时探索多条路径,如果您到达死路,我们会停止搜索这条路径,并允许我们尚未探索的其他路径继续探索。

这是我写的一些示例代码。为了使事情变得简单,我从StackOverflow中读取图像,将图像转换为黑白,并将图像镂空。不幸的是,您需要将此转换为逻辑运算,才能使此算法起作用。我明白你并不希望这样做,但我假设你会有这些痕迹的多个实例,所以如果你在一个连续的容器中标记一个点,这个算法将会标记属于这个容器的所有点。

在任何情况下,我都会将其镂空,以使容器的厚度为1像素厚,以使事情更轻松。我还创建了一个镂空图像的颜色版本,以便我们可以在我们探测过的像素中以红色着色。代码之后的第一件事就是它会向您显示镂空图像,并等待您沿着容器点击某处。这是通过ginput完成的。该代码将找到与您点击的位置相关的最近点,并使其成为起点。这是通过简单地找到最小的欧几里德距离与你点击的每个有效点在船上的点。

一旦我们找到了这个起点,我们就把它作为第一个进入我们的队列并开始我们的BFS算法。作为奖励,我还编写了代码以保存进度为动画GIF。每20帧,一个图像被写入这个动画GIF文件。另外,我会告诉你每20帧的线追踪的样子。这一直持续下去,直到我们用完点或队列为空,然后算法停止。动画GIF也存储在您运行代码的同一目录中。我还写了最终完成的图像的样子,因为当我们停止算法时,它不会发生在20帧的倍数上,所以您应该确定要写入最后一帧和最后一帧,这应该是完全标记的血管图像。

事不宜迟,下面的代码:

% // Read in the image from StackOverflow 
im = imread('http://i.stack.imgur.com/3t4Dx.png'); 

%// Skeletonize the image to simplify problem 
im = bwmorph(~im2bw(im), 'skel', 'inf'); 

%// Make a colour version so that we can mark pixels we have visited in 
%// red 
im_colour = 255*uint8(cat(3,im,im,im)); 

%// Get a starting point from the user 
imshow(im); 
[col,row] = ginput(1); 
close all; 

%// Find the closest point on the vessel where we have clicked and 
%// add to the queue as a starting point 
[rows,cols] = find(im); 
[~,ind] = min((row-rows).^2 + (col-cols).^2); 
queue = [rows(ind), cols(ind)]; 

%// Variable that stores all the locations we have visited so far 
mask = false(size(im)); 

%// To save animated GIF to file 
filename = 'linetracing.gif'; 
figure; 

%// Counter that keeps track of how many points we have processed so far 
%// This also allows us to write the line tracing algorithm output at 
%// certain iteration numbers to output 
n = 1; 

%// While the queue is not empty 
while ~isempty(queue) 

    %// Dequeue 
    pt = queue(1,:); 
    queue(1,:) = []; 

    %// If this is not a valid vessel point, mark as visited and continue 
    if im(pt(1),pt(2)) == 0 
     mask(pt(1),pt(2)) = true;  

    %// If we have visited this point, continue 
    elseif mask(pt(1),pt(2)) 
     continue;   
    else 
     %// We haven't visited this point yet 
     %// Mark this as visited 
     mask(pt(1),pt(2)) = true; 

     %// Colour the image at this point 
     im_colour(pt(1),pt(2),:) = [255;0;0];        

     %// We will write the progress of our line tracing every 20 frames 
     %// If we are at the first frame, we need to initialize our GIF 
     %// writing. Loop the GIF animation forever when viewing it 
     if n == 1 
      [imind,cm] = rgb2ind(im_colour,256); 
      imshow(im_colour); 
      imwrite(imind, cm, filename, 'Loopcount', inf); 
     %// For every 20th frame, add the progress to our GIF 
     elseif mod(n,20) == 0 
      [imind,cm] = rgb2ind(im_colour,256); 
      imshow(im_colour); 
      imwrite(imind, cm, filename, 'WriteMode', 'append'); 
     end 
     %// Increment counter 
     n = n + 1; 

     %// Find neighbouring points that surround current point 
     %// and only select those that we haven't visited 
     [c,r] = meshgrid(pt(2)-1:pt(2)+1,pt(1)-1:pt(1)+1); 
     ind = sub2ind(size(im), r, c); 
     locs = im(ind); 
     r = r(locs); 
     c = c(locs); 

     %// Enqueue 
     queue = [queue; r(:) c(:)]; 
    end 
end 

%// Write the very last frame in case we don't get to do that. Only 
%//happens if the count is not a multiple of 20. 
imshow(im_colour); 
[imind,cm] = rgb2ind(im_colour,256); 
imwrite(imind, cm, filename, 'WriteMode', 'append'); 

下面是该代码为GIF动画的一个实例运行。我的出发点与您在帖子中标记示例的地方相同。

enter image description here


希望这将让你开始。祝你好运!

+0

哇太棒了!我将这个问题标记为非常酷的东西! +1或课程:) – 2014-12-08 19:54:01

+0

@ Benoit_11 - Merci beaucoup mon ami :) – rayryeng 2014-12-08 20:43:23

+0

Çame fait plaisir!老实说,我看到了这个问题,虽然我觉得很有趣,但我对于如何解决这个问题感到非常困惑。你再次把它钉在了好的位置:) – 2014-12-08 20:45:35