2014-12-07 161 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