{"id":134,"date":"2007-05-11T12:12:59","date_gmt":"2007-05-11T16:12:59","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2007\/05\/11\/connected-component-labeling-part-5\/"},"modified":"2019-10-23T12:54:06","modified_gmt":"2019-10-23T16:54:06","slug":"connected-component-labeling-part-5","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2007\/05\/11\/connected-component-labeling-part-5\/","title":{"rendered":"Connected component labeling &#8211; Part 5"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>OK, I've learned an important lesson about this blog: I really shouldn't start up two topics series at the same time.  It's\r\n      too hard to find the time to compose posts on both topics each week, and so the frequency of my posts drops off.\r\n   <\/p>\r\n   <p>Anyway, let's get into the third algorithm for labeling connected components in a binary image.  It involves two passes over\r\n      the image, with an in-between step called <i>equivalence class resolution<\/i>.  I first learned about this idea from Haralick and Shapiro, <i>Computer and Robot Vision<\/i>, vol. I, Addison-Wesley, 1992.\r\n   <\/p>\r\n   <p>The first pass assigns temporary labels to each foreground pixel. Here's a graphical illustration of that procedure, using\r\n      this small sample image:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig1.png\"> <\/p>\r\n   <p>Now scan the image, processing one pixel at a time.  Because of the way MATLAB stores matrix elements in memory, we'll scan\r\n      along columns. When the scan encounters a foreground pixel, look at that pixel's neighbors <b>that have already been encountered in the scan<\/b>.  Here's the first foregound pixel encountered, shown with its already-scanned neighbors highlighted in color:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig2.png\"> <\/p>\r\n   <p>For the pixel shown above, none of the highlighted neighbors have been assigned a temporary label yet, so a new label value\r\n      (1) is assigned to the corresponding pixel in the output.\r\n   <\/p>\r\n   <p>Here's the second foregound pixel encountered:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig3.png\"> <\/p>\r\n   <p>Note that one of this pixel's neighbors has already received a label (1), so this pixel is also assigned a temporary label\r\n      of 1 in the output image.\r\n   <\/p>\r\n   <p>When the scan gets to row 2, column 4 pixel, none of that pixel's scanned neighbors have been labeled, so that pixel gets\r\n      assigned a new temporary label of 2.\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig4.png\"> <\/p>\r\n   <p>The very next pixel, on row 3, column 4, is where things start to get more interesting:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig5.png\"> <\/p>\r\n   <p>One of this pixel's scanned neighbors has already been assigned a label of 1, but another of the neighbors has been assigned\r\n      a label of 2. So the algorithm picks one of the labels arbitrarily, and then records the fact that temporary label 1 and temporary\r\n      label 2 actually refer to the same object.\r\n   <\/p>\r\n   <p>This situation happens again on row 4, column 8:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig7.png\"> <\/p>\r\n   <p>So the pair of labels 3 and 4 is an <i>equivalence<\/i> and goes into the <i>equivalence table<\/i>.\r\n   <\/p>\r\n   <p>When the first pass is done, you have this matrix of labels:<\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig8.png\"> <\/p>\r\n   <p>And you have an equivalence table containing these pairs:<\/p><pre> 1 &lt;--&gt; 2\r\n 3 &lt;--&gt; 4<\/pre><p><i>Equivalence class resolution<\/i> is the process of determining which subsets of the temporary labels really refer to the same object.  You can do that in\r\n      MATLAB using the technique I <a href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/03\/20\/connected-component-labeling-part-3\/\">showed previously<\/a> that was based adjacency matrix and <tt>dmperm<\/tt>.  From this you would compute that temporary labels 1 and 2 map to final label 1, and temporary labels 3 and 4 map to final\r\n      label 2.  Then you make a second pass over the output matrix to relabel the pixels according to this mapping:\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2007\/cclabel_part5_fig9.png\"> <\/p>\r\n   <p>The Image Processing Toolbox function <tt>bwlabeln<\/tt> uses a variation of this technique, where the equivalence class resolution is actually performed during the first pass, using\r\n      an algorithm called <i>union find<\/i>.  I'll explain that next time.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_5e3236b961394a9db75c89d928db5641() {\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='5e3236b961394a9db75c89d928db5641 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 5e3236b961394a9db75c89d928db5641';\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 2007 The MathWorks, Inc.';\r\n\r\n        w = window.open();\r\n        d = w.document;\r\n        d.write('<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>\\n');\r\n      \r\n      d.title = title + ' (MATLAB code)';\r\n      d.close();\r\n      }   \r\n      \r\n-->\r\n<\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_5e3236b961394a9db75c89d928db5641()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n            the MATLAB code \r\n            <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.4<br><\/p>\r\n<\/div>\r\n<!--\r\n5e3236b961394a9db75c89d928db5641 ##### SOURCE BEGIN #####\r\n%% Connected component labeling - part 5\r\n% OK, I've learned an important lesson about this blog: I really shouldn't\r\n% start up two topics series at the same time.  It's too hard to find the \r\n% time to compose posts on both topics each week, and so the frequency of\r\n% my posts drops off.\r\n%\r\n% Anyway, let's get into the third algorithm for labeling connected\r\n% components in a binary image.  It involves two passes over the image,\r\n% with an in-between step called _equivalence class resolution_.  I first\r\n% learned about this idea from Haralick and Shapiro, _Computer and\r\n% Robot Vision_, vol. I, Addison-Wesley, 1992.\r\n%\r\n% The first pass assigns temporary labels to each foreground pixel. Here's\r\n% a graphical illustration of that procedure, using this small sample\r\n% image:\r\n%\r\n% <<cclabel_part5_fig1.png>>\r\n%\r\n% Now scan the image, processing one pixel at a time.  Because of the way\r\n% MATLAB stores matrix elements in memory, we'll scan along columns. When\r\n% the scan encounters a foreground pixel, look at that pixel's neighbors\r\n% *that have already been encountered in the scan*.  Here's the first\r\n% foregound pixel encountered, shown with its already-scanned neighbors\r\n% highlighted in color:\r\n%\r\n% <<cclabel_part5_fig2.png>>\r\n%\r\n% For the pixel shown above, none of the highlighted neighbors have been\r\n% assigned a temporary label yet, so a new label value (1) is assigned to\r\n% the corresponding pixel in the output.\r\n%\r\n% Here's the second foregound pixel encountered:\r\n%\r\n% <<cclabel_part5_fig3.png>>\r\n%\r\n% Note that one of this pixel's neighbors has already received a label (1),\r\n% so this pixel is also assigned a temporary label of 1 in the output\r\n% image.\r\n%\r\n% When the scan gets to row 2, column 4 pixel, none of that pixel's scanned\r\n% neighbors have been labeled, so that pixel gets assigned a new temporary\r\n% label of 2.\r\n%\r\n% <<cclabel_part5_fig4.png>>\r\n%\r\n% The very next pixel, on row 3, column 4, is where things start to get\r\n% more interesting:\r\n%\r\n% <<cclabel_part5_fig5.png>>\r\n%\r\n% One of this pixel's scanned neighbors has already been assigned a label\r\n% of 1, but another of the neighbors has been assigned a label of 2. So the\r\n% algorithm picks one of the labels arbitrarily, and then records the fact\r\n% that temporary label 1 and temporary label 2 actually refer to the same\r\n% object.\r\n%\r\n% This situation happens again on row 4, column 8:\r\n%\r\n% <<cclabel_part5_fig7.png>>\r\n%\r\n% So the pair of labels 3 and 4 is an _equivalence_ and goes into the \r\n% _equivalence table_.\r\n%\r\n% When the first pass is done, you have this matrix of labels:\r\n%\r\n% <<cclabel_part5_fig8.png>>\r\n%\r\n% And you have an equivalence table containing these pairs:\r\n%\r\n%   1 <REPLACE_WITH_DASH_DASH> 2\r\n%   3 <REPLACE_WITH_DASH_DASH> 4\r\n%\r\n% _Equivalence class resolution_ is the process of determining which\r\n% subsets of the temporary labels really refer to the same object.  You can\r\n% do that in MATLAB using the technique I <https:\/\/blogs.mathworks.com\/steve\/2007\/03\/20\/connected-component-labeling-part-3\/ \r\n% showed previously> that was based\r\n% adjacency matrix and |dmperm|.  From this you would compute that\r\n% temporary labels 1 and 2 map to final label 1, and temporary labels 3 and\r\n% 4 map to final label 2.  Then you make a second pass over the output\r\n% matrix to relabel the pixels according to this mapping:\r\n%\r\n% <<cclabel_part5_fig9.png>>\r\n%\r\n% The Image Processing Toolbox function |bwlabeln| uses a variation of this\r\n% technique, where the equivalence class resolution is actually performed\r\n% during the first pass, using an algorithm called _union find_.  I'll\r\n% explain that next time.\r\n\r\n##### SOURCE END ##### 5e3236b961394a9db75c89d928db5641\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   OK, I've learned an important lesson about this blog: I really shouldn't start up two topics series at the same time.  It's\r\n      too hard to find the time to compose posts on both topics each... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/05\/11\/connected-component-labeling-part-5\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[352],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/134"}],"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=134"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/134\/revisions"}],"predecessor-version":[{"id":3530,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/134\/revisions\/3530"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=134"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=134"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=134"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}