{"id":219,"date":"2008-07-14T13:49:35","date_gmt":"2008-07-14T17:49:35","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2008\/07\/14\/opening-by-reconstruction\/"},"modified":"2019-10-28T09:36:18","modified_gmt":"2019-10-28T13:36:18","slug":"opening-by-reconstruction","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2008\/07\/14\/opening-by-reconstruction\/","title":{"rendered":"Opening by reconstruction"},"content":{"rendered":"<div class=\"content\">\r\n\r\nToday I want to show you a morphological operation called \"opening by reconstruction.\"\r\n\r\nThe normal morphological opening is an erosion followed by a dilation. The erosion \"shrinks\" an image according to the shape\r\nof the structuring element, removing objects that are smaller than the shape. Then the dilation step \"regrows\" the remaining\r\nobjects by the same shape.\r\n\r\nHere's an example using a fragment of text from the book Digital Image Processing Using MATLAB.\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">url = <span style=\"color: #a020f0;\">'https:\/\/blogs.mathworks.com\/images\/steve\/2008\/book_text.png'<\/span>;\r\ntext = imread(url);\r\nbw = text(1:500, 1:500);\r\nimshow(bw)<\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2008\/opening_by_reconstruction_example_01.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nSuppose we want to identify characters containing a tall vertical segment. We can do this by opening with a vertical structuring\r\nelement.\r\n\r\nErode first:\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">se = strel(ones(51, 1));\r\nbw2 = imerode(bw, se);\r\nimshow(bw2)<\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2008\/opening_by_reconstruction_example_02.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nThen dilate:\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">bw3 = imdilate(bw2, se);\r\nimshow(bw3)<\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2008\/opening_by_reconstruction_example_03.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nOr you can do the opening in a single step by calling imopen:\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">bw3 = imopen(bw, se);\r\nimshow(bw3)<\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2008\/opening_by_reconstruction_example_04.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nThe dilation step in the opening operation restored the vertical strokes, but the other strokes of the characters are missing.\r\nHow can we get the entire characters containing vertical strokes?\r\n\r\nThe answer is to use morphological reconstruction. For binary images, reconstruction starts from a set of starting pixels\r\n(or \"seed\" pixels) and then grows in flood-fill fashion to include complete connected components.\r\n\r\nTo get ready to use reconstruction, first define a \"marker\" image. This is the image containing the starting or seed locations.\r\nFor our text example, the marker image will the output of the erosion.\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">marker = imerode(bw, se);\r\nimshow(marker)<\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2008\/opening_by_reconstruction_example_05.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nNext, define mask image. The flood-filling will be constrained to spread only to foreground pixels in the mask image. We\r\ncan use the original text image as our reconstruction mask.\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">mask = bw;<\/pre>\r\nFinally, call <a href=\"https:\/\/www.mathworks.com\/help\/images\/ref\/imreconstruct.html\"><tt>imreconstruct<\/tt><\/a> to perform the operation.\r\n<pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid #c8c8c8;\">characters = imreconstruct(marker, mask);\r\nimshow(characters)<\/pre>\r\n<img decoding=\"async\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2008\/opening_by_reconstruction_example_06.png\" alt=\"\" hspace=\"5\" vspace=\"5\" \/>\r\n\r\nPerforming morphological reconstruction, using the eroded image as the marker and the original image as the mask, is called\r\n\"opening by reconstruction.\"\r\n\r\nDo you have other uses for morphological reconstruction in your own applications? Tell us about it: Click on the \"Comment\"\r\nlink below.\r\n\r\n<script language=\"JavaScript\">\/\/ <![CDATA[\r\n\r\n\r\n    function grabCode_8d0208282c434669b68cef12a5900bf2() {\r\n        \/\/ Remember the title so we can use it in the new page\r\n        title = document.title;\r\n\r\n        \/\/ Break up these strings so that their presence\r\n        \/\/ in the Javascript doesn't mess up the search for\r\n        \/\/ the MATLAB code.\r\n        t1='8d0208282c434669b68cef12a5900bf2 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 8d0208282c434669b68cef12a5900bf2';\r\n\r\n        b=document.getElementsByTagName('body')[0];\r\n        i1=b.innerHTML.indexOf(t1)+t1.length;\r\n        i2=b.innerHTML.indexOf(t2);\r\n\r\n        code_string = b.innerHTML.substring(i1, i2);\r\n        code_string = code_string.replace(\/REPLACE_WITH_DASH_DASH\/g,'--');\r\n\r\n        \/\/ Use \/x3C\/g instead of the less-than character to avoid errors \r\n        \/\/ in the XML parser.\r\n        \/\/ Use '\\x26#60;' instead of '<' so that the XML parser\r\n        \/\/ doesn't go ahead and substitute the less-than character. \r\n        code_string = code_string.replace(\/\\x3C\/g, '\\x26#60;');\r\n\r\n        author = 'Steve Eddins';\r\n        copyright = 'Copyright 2008 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('\r\n\r\n<pre>\\n');\r\n        d.write(code_string);\r\n\r\n        \/\/ Add author and copyright lines at the bottom if specified.\r\n        if ((author.length > 0) || (copyright.length > 0)) {\r\n            d.writeln('');\r\n            d.writeln('%%');\r\n            if (author.length > 0) {\r\n                d.writeln('% _' + author + '_');\r\n            }\r\n            if (copyright.length > 0) {\r\n                d.writeln('% _' + copyright + '_');\r\n            }\r\n        }\r\n\r\n        d.write('<\/pre>\r\n\r\n\r\n\\n');\r\n\r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n\r\n\/\/ ]]><\/script>\r\n<p style=\"text-align: right; font-size: xx-small; font-weight: lighter; font-style: italic; color: gray;\"><a><span style=\"font-size: x-small; font-style: italic;\">Get\r\nthe MATLAB code\r\n<noscript>(requires JavaScript)<\/noscript><\/span><\/a><\/p>\r\nPublished with MATLAB\u00ae 7.6\r\n\r\n<\/div>\r\n<!--\r\n8d0208282c434669b68cef12a5900bf2 ##### SOURCE BEGIN #####\r\n%% Opening by reconstruction\r\n% Today I want to show you a morphological operation called \"opening\r\n% by reconstruction.\"\r\n%\r\n% The normal morphological opening is an erosion followed by a\r\n% dilation. The erosion \"shrinks\" an image according to the shape of\r\n% the structuring element, removing objects that are smaller than\r\n% the shape.  Then the dilation step \"regrows\" the remaining objects\r\n% by the same shape.\r\n%\r\n% Here's an example using a fragment of text from the book\r\n% Digital Image Processing Using MATLAB.\r\n\r\nurl = 'https:\/\/blogs.mathworks.com\/images\/steve\/2008\/book_text.png';\r\ntext = imread(url);\r\nbw = text(1:500, 1:500);\r\nimshow(bw)\r\n\r\n%%\r\n% Suppose we want to identify characters containing a tall\r\n% vertical segment.  We can do this by opening with a vertical\r\n% structuring element.\r\n%\r\n% Erode first:\r\n\r\nse = strel(ones(51, 1));\r\nbw2 = imerode(bw, se);\r\nimshow(bw2)\r\n\r\n%%\r\n% Then dilate:\r\n\r\nbw3 = imdilate(bw2, se);\r\nimshow(bw3)\r\n\r\n%%\r\n% Or you can do the opening in a single step by calling imopen:\r\n\r\nbw3 = imopen(bw, se);\r\nimshow(bw3)\r\n\r\n%%\r\n% The dilation step in the opening operation restored the\r\n% vertical strokes, but the other strokes of the characters are\r\n% missing. How can we get the entire characters containing\r\n% vertical strokes?\r\n%\r\n% The answer is to use morphological reconstruction.  For binary\r\n% images, reconstruction starts from a set of starting pixels (or\r\n% \"seed\" pixels) and then grows in flood-fill fashion to include\r\n% complete connected components.\r\n%\r\n% To get ready to use reconstruction, first define a \"marker\"\r\n% image.  This is the image containing the starting or seed\r\n% locations.  For our text example, the marker image will the\r\n% output of the erosion.\r\n\r\nmarker = imerode(bw, se);\r\nimshow(marker)\r\n\r\n%%\r\n% Next, define mask image.  The flood-filling will be constrained\r\n% to spread only to foreground pixels in the mask image.  We can\r\n% use the original text image as our reconstruction mask.\r\n\r\nmask = bw;\r\n\r\n%%\r\n% Finally, call\r\n% <https:\/\/www.mathworks.com\/help\/images\/index.htmlimreconstruct.html\r\n% |imreconstruct|> to perform the operation.\r\n\r\ncharacters = imreconstruct(marker, mask);\r\nimshow(characters)\r\n\r\n%%\r\n% Performing morphological reconstruction, using the eroded image\r\n% as the marker and the original image as the mask, is called\r\n% \"opening by reconstruction.\"\r\n%\r\n% Do you have other uses for morphological reconstruction in your\r\n% own applications?  Tell us about it: Click on the \"Comment\"\r\n% link below.\r\n\r\n##### SOURCE END ##### 8d0208282c434669b68cef12a5900bf2\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n\r\nToday I want to show you a morphological operation called \"opening by reconstruction.\"\r\n\r\nThe normal morphological opening is an erosion followed by a dilation. The erosion \"shrinks\" an image... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2008\/07\/14\/opening-by-reconstruction\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[124,246,108,76,438,36,288,106,78],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/219"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/users\/42"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/comments?post=219"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/219\/revisions"}],"predecessor-version":[{"id":1291,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/219\/revisions\/1291"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=219"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=219"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=219"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}