2015-06-15 3 views
1

Я пытаюсь создать маску (или аналогичный результат), чтобы стереть фрагменты двоичного изображения, которые не привязаны к объекту, окруженному границей. Я видел эту нить (http://www.mathworks.com/matlabcentral/answers/120579-converting-boundary-to-mask), чтобы сделать это из bwboundaries, но у меня возникли проблемы с внесением в нее подходящих изменений. Моя цель - использовать этот код, чтобы изолировать часть этой карты топографии, которая подключена, и избавиться от лишних частей. Мне нужно сохранить структуру внутри ограниченной области, так как тогда я собирался использовать bw-границы для создания дополнительных граничных линий «внутренней» структуры основного объекта.Создать маску из bwtraceboundary в Matlab

enter image description here

Ниже мой код, чтобы сначала создать единую пограничную линию с помощью функции поиска для нижнего левого пикселя черной области, чтобы начать трассировку. Он просто ищет первый столбец изображения, который не является полностью белым, и выбирает последний черный пиксель. Второй раздел должен был создать внутренние граничные линии. Обратите внимание, что я пытаюсь выполнить этот двухэтапный процесс, но если есть способ сделать это только с одним, я бы тоже хотел услышать это решение. В конечном счете, мне просто нужны границы для основной, большой черной области и отверстий внутри нее, в то же время избавляясь от лишних предметов, висящих вокруг.

figName='Images/BookTrace_1'; 

BW = imread([figName,'.png']); 
    BW=im2bw(BW); 
    imshow(BW,[]); 

    for j=1:size(BW,2) 
     if sum(BW(:,j))~=sum(BW(:,1)) 
      corner=BW(:,j); 
      c=j-1; 
      break 
     end 
    end 
    r=find(corner==0); 
    r=r(end); 

    outline = bwtraceboundary(BW,[r c],'W',8,Inf,'counterclockwise'); 
    hold on; 
    plot(outline(:,2),outline(:,1),'g','LineWidth',2); 


[B,L] = bwboundaries(BW); 
hold on 
for k = 1:length(B) 
    boundary = B{k}; 
    plot(boundary(:,2), boundary(:,1), 'g', 'LineWidth', 2) 
end 

Любые предложения или советы приветствуются. Если есть вопросы, пожалуйста, дайте мне знать, и я обновить сообщение. Спасибо!

EDIT: Для пояснения моя конечная цель такова, как на рисунке ниже. Мне нужно проследить все внешние и внутренние границы, привязанные к основному объекту, при этом исключая любые запасные мелкие кусочки, которые не привязаны к нему. enter image description here

ответ

5

Это очень просто. На самом деле я бы не использовал вышеприведенный код и вместо этого использовал панель обработки изображений. Существует встроенная функция для удаления любых белых пикселей, которые касаются границы изображения. Используйте функцию imclearborder.

Функция вернет новое двоичное изображение, в котором будут удалены любые пиксели, которые касаются границ изображения. Учитывая, что ваш код, это очень просто:

out = imclearborder(BW); 

Используя выше изображение в качестве примера, я собираюсь порог так, что зеленые линии удаляются ... или, скорее, сливались с другими белыми пикселями, и Я позвоню выше функции:

BW = imread('http://i.stack.imgur.com/jhLOw.png'); %// Read from StackOverflow 
BW = im2bw(BW); %// Convert to binary 
out = imclearborder(BW); %// Remove pixels along border 
imshow(out); %// Show image 

получаем:

enter image description here


Если вам нужен противоположный эффект, когда вы хотите сохранить границы и удалить все остальное внутри, просто создайте новое изображение, скопировав исходный файл и используйте вывод из вышеописанного, чтобы обнулить эти пиксельные местоположения.

out2 = BW; %// Make copy 
out2(out) = 0; %// Set pixels not belonging to boundary to 0 
imshow(out2); %// Show image 

Таким образом, мы получаем:

enter image description here

Редактировать

Учитывая вышеизложенное желаемый результат, я считаю, я знаю, что вы хотите прямо сейчас. Вы хотите заполнить отверстия для каждой группы пикселей и проследить вдоль границы желаемого результата.Тот факт, что мы разделили его на две категории, будет полезен. Для тех объектов, которые находятся внутри, используйте функцию imfill и укажите опцию holes, чтобы заполнить любые черные дыры так, чтобы они были белыми. Для внешних объектов это потребует немного работы. То, что я сделал бы, это инвертировать изображение так, чтобы пиксели, которые были черными, стали белыми и наоборот, затем используйте функцию bwareaopen, чтобы удалить все пиксели, площадь которых ниже определенной величины. Это позволит удалить те небольшие изолированные черные области, которые находятся вдоль границы внешних областей. Как только вы закончите, повторно инвертируйте изображение. Эффект от этого заключается в том, что небольшие отверстия будут устранены. Я выбрал порог 500 пикселей для области ... кажется, хорошо работает.

Таким образом, с помощью указанных выше переменных в качестве ссылки, выполните следующие действия:

%// Fill holes for both regions separately 
out_fill = imfill(out, 'holes'); 
out2_fill = ~bwareaopen(~out2, 500); 

%// Merge together 
final_out = out_fill | out2_fill; 

Это то, что мы получаем:

enter image description here

Если вы хотите хороший зеленый границу, как в вашем примере с иллюстрируют этот момент, вы можете сделать это:

perim = bwperim(final_out); 
red = final_out; 
green = final_out; 
blue = final_out; 
red(perim) = 0; 
blue(perim) = 0; 
out_colour = 255*uint8(cat(3, red, green, blue)); 
imshow(out_colour); 

Приведенные выше код находит периметр объектов, то мы создаем новый образ, где красные и синие каналы по периметру устанавливается в 0, при установке зеленого канала 255.

Мы получаем это:

enter image description here

Вы можете игнорировать зеленую границу пикселя, которая окружает изображение. Это просто побочный эффект, когда я нахожу периметр вдоль объектов на изображении. Фактически, изображение, которое вы мне предоставили, имеет белую границу пикселя, которая окружает весь регион, поэтому я не уверен, что это предназначено, или если это часть всей великой схемы вещей.


Для закрепления в рабочем примере, так что вы можете скопировать и вставить в MATLAB, вот весь код в один блок кода:

%// Pre-processing 
BW = imread('http://i.stack.imgur.com/jhLOw.png'); %// Read from StackOverflow 
BW = im2bw(BW); %// Convert to binary 

out = imclearborder(BW); %// Remove pixels along border 

%// Obtain pixels that are along border 
out2 = BW; %// Make copy 
out2(out) = 0; %// Set pixels not belonging to boundary to 0 

%// Fill holes for both regions separately 
out_fill = imfill(out, 'holes'); 
out2_fill = ~bwareaopen(~out2, 500); 

%// Merge together 
final_out = out_fill | out2_fill; 

%// Show final output 
figure; 
imshow(final_out); 

%// Bonus - Show perimeter of output in green 
perim = bwperim(final_out); 
red = final_out; 
green = final_out; 
blue = final_out; 
red(perim) = 0; 
blue(perim) = 0; 
out_colour = 255*uint8(cat(3, red, green, blue)); 
figure; 
imshow(out_colour); 
+0

Это отличная функция, чтобы узнать о! Прошу прощения, я думаю, что, возможно, я не совсем понял, что мне нужно. Я хочу удалить все за пределами зеленой границы, но держать все внутри. Значит, эти два варианта дают мне только один или другой, если я не пойму? – jmolaro

+0

@jmolaro Прошу прощения, я не понимаю ... если вы хотите удалить все за пределами зеленой границы, не будет ли это вторым вариантом? Можете ли вы показать мне, как выглядит идеальный результат? – rayryeng

+0

@jmolaro - ОК, вы хотите удалить эти пиксели в изображении, которые обозначены зеленым? Я до сих пор не совсем понимаю, чего вы хотите. – rayryeng

Смежные вопросы