使用MATLAB进行线跟踪

fft*_*tyy 1 matlab image-processing line

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

它是关于视网膜血管检测.我发现了一篇关于它的文章,但我不知道创建动态搜索窗口的方法.

我怎样才能做到这一点?

原始图片:在此输入图像描述

跟踪方式: 在此输入图像描述

我用油漆准备了图像.

ray*_*ica 6

这是一个经典的广度优先搜索(BFS)问题.您可以将您的示例中标记的起点视为进入迷宫的切入点,在该迷宫中,您的工作将从迷宫中找到出路.BFS背后的基本驱动力是它使用队列.在起点处,将此点添加到队列中.然后,当队列不为空时,将该点从队列中取出,然后检查其任何邻居以查看您是否:

  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');
Run Code Online (Sandbox Code Playgroud)

以下是此代码作为动画GIF运行的示例.我的起点与您在帖子中标记示例的位置大致相同.

在此输入图像描述


希望这会让你开始.祝好运!