Intrepid MathWorks application engineer Brett Shoelson recently got a user question that caught my attention. Consider an image containing text characters in outline form, such as this:
url = 'https://blogs.mathworks.com/steve/files/MathWorks-address-binary.png'; bw = imread(url); imshow(bw)
How can we fill in the text characters from their outlines without filling in the internal holes? If we just use imfill with the 'holes' option, you can see that it doesn't give us the desired result.
bw_filled = imfill(bw,'holes'); imshow(bw_filled) title('Original with holes filled')
When I saw this problem, I thought that some combination of imfill, imclearborder, and logical operators could possibly solve it.
You've already seen imfill. Here's how imclearborder works.
url_sample = 'https://blogs.mathworks.com/images/steve/168/aug31.png'; bw_sample = imread(url_sample); imshow(bw_sample) title('imclearborder demonstration - input image')
bw_sample_clearborder = imclearborder(bw_sample); imshow(bw_sample_clearborder) title('imclearborder demonstration - output image')
You can see that any connected component touching any image border has been removed.
Going back to our task, I'm going to proceed first by identifying the background pixels that are inside the text characters. Roughly speaking, I'll tackle this phase by working "from the outside in."
First, let's identify and remove the pixels that are external to the characters.
bw2 = ~bw; imshow(bw2) title('Complement of original image')
bw3 = imclearborder(bw2); imshow(bw3) title('External pixels removed from the foreground')
Now let's complement the image and clear the borders again.
bw4 = ~bw3; imshow(bw4) title('Complement of bw3')
bw5 = imclearborder(bw4); imshow(bw5) title('After second border-clearing')
If we fill the holes in the image bw5 above, and then take the exclusive-or of the result with bw5 we'll be left only with the internal hole pixels inside the characters.
bw6 = imfill(bw5,'holes'); bw7 = xor(bw6,bw5); imshow(bw7) title('Internal hole pixels')
We're almost there. We can now use bw6 to "fix up" the initial filled result, bw_filled, using an exclusive-or operation.
bw_final = xor(bw_filled,bw7); imshow(bw_final) title('Presto!')
Readers, how would you solve this problem? Brett and I think there might be a couple of other reasonable approaches. Let us know in the comments.
To leave a comment, please click here to sign in to your MathWorks Account or create a new one.