I'm trying to create a mask (or similar result) in order to erase pieces of a binary image that are not attached to the object surrounded by the boundary. I saw this thread (http://www.mathworks.com/matlabcentral/answers/120579-converting-boundary-to-mask) to do this from bwboundaries, but I'm having trouble making suitable changes to it. My goal is to use this code to isolate the part of this topography map that is connected, and get rid of the extra pieces. I need to retain the structure inside of the bounded area, as I was then going to use bwboundaries to create additional boundary lines of the main object's "interior" structure.
The following is my code to first create the single boundary line by searching for the bottom left pixel of the black area to begin the trace. It just looks for the first column of the image that isn't completely white and selects the last black pixel. The second section was then to create the inner boundary lines. Note that I am attempting this two step process, but if there is a way to do it with only one I'd like to hear that solution as well. Ultimately I just want boundaries for the main, large black area and the holes inside of it, while getting rid of the extra pieces hanging around.
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
Any suggestions or tips are greatly appreciated. If there are questions, please let me know and I'll update the post. Thank you!
EDIT: For clarification, my end goal is as in the below image. I need to trace all of the outer and inner boundaries attached to the main object, while eliminating any spare small pieces that are not attached to it.
It's very simple. I actually wouldn't use the code above and use the image processing toolbox instead. There's a built-in function to remove any white pixels that touch the border of the image. Use the
imclearborder
function.The function will return a new binary image where any pixels that were touching the borders of the image will be removed. Given your code, it's very simply:
Using the above image as an example, I'm going to threshold it so that the green lines are removed... or rather merged with the other white pixels, and I'll call the above function:
We get:
If you want the opposite effect, where you want to retain the boundaries and remove everything else inside, simply create a new image by copying the original one and use the output from the above to null these pixel locations.
We thus get:
Edit
Given the above desired output, I believe I know what you want now. You wish to fill in the holes for each group of pixels and trace along the boundary of the desired result. The fact that we have this split up into two categories is going to be useful. For those objects that are in the interior, use the
imfill
function and specify theholes
option to fill in any of the black holes so that they're white. For the objects that exterior, this will need a bit of work. What I would do is invert the image so that pixels that are black become white and vice-versa, then use thebwareaopen
function to clear away any pixels whose area is below a certain amount. This will remove those small isolated black regions that are along the border of the exterior regions. Once you're done, re-invert the image. The effect of this is that the small holes will be eliminated. I chose a threshold of 500 pixels for the area... seems to work well.Therefore, using the above variables as reference, do this:
This is what we get:
If you want a nice green border like in your example to illustrate this point, you can do this:
The above code finds the perimeter of the objects, then we create a new image where the red and blue channels along the perimeter are set to 0, while setting the green channel to 255.
We get this:
You can ignore the green pixel border that surrounds the image. That's just a side effect with the way I'm finding the perimeter along the objects in the image. In fact, the image you supplied to me had a white pixel border that surrounds the whole region, so I'm not sure if that's intended or if that's part of the whole grand scheme of things.
To consolidate into a working example so that you can copy and paste into MATLAB, here's all of the code in one code block: