{"id":395,"date":"2011-11-01T13:57:03","date_gmt":"2011-11-01T17:57:03","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2011\/11\/01\/exploring-shortest-paths-part-1\/"},"modified":"2019-10-29T16:58:48","modified_gmt":"2019-10-29T20:58:48","slug":"exploring-shortest-paths-part-1","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2011\/11\/01\/exploring-shortest-paths-part-1\/","title":{"rendered":"Exploring shortest paths &#8211; part 1"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>Blog reader <a href=\"https:\/\/blogs.mathworks.com\/steve\/2009\/01\/28\/have-you-heard-of-the-feature-transform\/#comment-24580\">Bogdan<\/a> asked this question last week:\r\n   <\/p>\r\n   <p><i>I am trying to find the length and location of the shortest path between objects. It seems like some application of bwdist\r\n         should be able to do this. Any advice? Example:<\/i><\/p><pre>1 0 1\r\n0 1 0\r\n0 0 0\r\n0 1 0\r\n1 0 1<\/pre><p><i>Should yield<\/i><\/p><pre>0 0 0\r\n0 0 0\r\n0 p 0\r\n0 0 0\r\n0 0 0<\/pre><p><i>With p = path length = 1<\/i><\/p>\r\n   <p>I agree, some application of <tt>bwdist<\/tt> should do it. Actually, there are several other useful functions that can be applied to this task, including <tt>imregionalmin<\/tt> and <tt>bwdistgeodesic<\/tt>, a new function that just shipped in R2011b.\r\n   <\/p>\r\n   <p>I've been tinkering with this problem off and on for a few days, and I think it might take a few posts to explore some of\r\n      the interesting ideas and issues posed by this problem. Today I'll start with the basics of using <tt>bwdist<\/tt> and <tt>imregionalmin<\/tt> to identify a set of shortest paths from one object to another.\r\n   <\/p>\r\n   <p>Let's use this simple test image to start our exploration.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = [ <span style=\"color: #0000FF\">...<\/span>\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0   ]<\/pre><pre style=\"font-style:oblique\">\r\nbw =\r\n\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n     0     1     1     0     0     0     0     0     0     0     0     0\r\n     0     1     1     0     0     0     0     0     0     0     0     0\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n     0     0     0     0     0     0     0     0     0     1     1     0\r\n     0     0     0     0     0     0     0     0     0     1     1     0\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n\r\n<\/pre><p>We want to find the shortest path (or paths!) from the upper left block of foreground pixels to the lower right block. The\r\n      key algorithmic idea is this:\r\n   <\/p>\r\n   <div>\r\n      <ol>\r\n         <li>Compute the distance transform for just the upper left block of foreground pixels.<\/li>\r\n         <li>Compute the distance transform for just the lower right block of foreground pixels.<\/li>\r\n         <li>Add the two distance transforms together.<\/li>\r\n         <li>The pixels in the regional minimum of the result lie along one or more of the shortest paths from one block to the other.<\/li>\r\n      <\/ol>\r\n   <\/div>\r\n   <p>(For reference, see P. Soille, Morphological Image Analysis: Principles and Applications, 2nd edition, Springer, 2003, section\r\n      7.3.4, \"Application to minimal path detection,\" pp. 233-234.)\r\n   <\/p>\r\n   <p>But we can't use the normal Euclidean distance transform because it doesn't correspond to a path traversal from one pixel\r\n      center to another. Rather, we have to use one of the distance transform approximations supported by <tt>bwdist<\/tt>: <tt>'chessboard'<\/tt>, <tt>'cityblock'<\/tt>, and <tt>'quasi-euclidean'<\/tt>.\r\n   <\/p>\r\n   <p>Here's how to do it using <tt>'quasi-euclidean'<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw1 = [ <span style=\"color: #0000FF\">...<\/span>\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0   ];\r\n\r\nbw2 = [ <span style=\"color: #0000FF\">...<\/span>\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0   ];\r\n\r\nD1 = bwdist(bw1, <span style=\"color: #A020F0\">'quasi-euclidean'<\/span>);\r\nD2 = bwdist(bw2, <span style=\"color: #A020F0\">'quasi-euclidean'<\/span>);\r\n\r\nD_sum = D1 + D2;\r\nD_sum(3:5, 3:10)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n    7.8284    7.8284    7.8284    7.8284    7.8284    7.8284    8.4142    9.0000\r\n    8.4142    7.8284    7.8284    7.8284    7.8284    7.8284    7.8284    8.4142\r\n    9.0000    8.4142    7.8284    7.8284    7.8284    7.8284    7.8284    7.8284\r\n\r\n<\/pre><p>You can see that the smallest value of <tt>D_sum<\/tt> is about 7.8284, and there's a set of pixels in-between the two objects that all have that value. The function <tt>imregionalmin<\/tt> identifies them all:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">path_pixels = imregionalmin(D_sum)<\/pre><pre style=\"font-style:oblique\">\r\npath_pixels =\r\n\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n     0     0     1     1     1     1     1     1     0     0     0     0\r\n     0     0     0     1     1     1     1     1     1     0     0     0\r\n     0     0     0     0     1     1     1     1     1     1     0     0\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n     0     0     0     0     0     0     0     0     0     0     0     0\r\n\r\n<\/pre><p>In the quasi-euclidean approximation to the distance transform, the distance from a pixel to one of its horizontal or vertical\r\n      neighbors is 1, and the distance from a pixel to one of its diagonal neighbors is sqrt(2). The result above says that the\r\n      shortest such path between the two objects is 7.8284. Furthermore, it says that there is more than one shortest path.\r\n   <\/p>\r\n   <p>I plan to explore this topic more fully this month. When using the quasi-euclidean distance transform, for example, there\r\n      are floating-point round-off issues that have to be dealt with when you try to apply the technique above to larger images.\r\n      Another issue is the effect of using different path-based distance transform approximations, such as <tt>'cityblock'<\/tt> or <tt>'chessboard'<\/tt>. Yet another issue is how to identify specific paths from the family of paths identified by <tt>imregionalmin<\/tt>. Along the way I'll experiment with different ways to visualize the results.\r\n   <\/p>\r\n   <p>Finally, I'll explore how to use a new function, <tt>bwdistgeodesic<\/tt>, to find shortest paths when there are constraints on where the paths can go.\r\n   <\/p>\r\n\r\n<h4>All the posts in this series<\/h4>\r\n      <ul>\r\n         <li>the basic idea of finding shortest paths by adding two distance transforms together (<a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/11\/01\/exploring-shortest-paths-part-1\/\">part 1<\/a>)\r\n         <\/li>\r\n         <li>the nonuniqueness of the shortest paths (<a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/11\/26\/exploring-shortest-paths-part-2\/\">part 2<\/a>)\r\n         <\/li>\r\n         <li>handling floating-point round-off effects (<a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/12\/02\/exploring-shortest-paths-part-3\/\">part 3<\/a>)\r\n         <\/li>\r\n         <li>using thinning to pick out a single path (<a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/12\/06\/exploring-shortest-paths-part-4\/\">part 4<\/a>)\r\n         <\/li>\r\n         <li>using <tt>bwdistgeodesic<\/tt> to find shortest paths subject to constraint (<a href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/12\/13\/exploring-shortest-paths-part-5\/\">part 5<\/a>)\r\n         <\/li>\r\n      <\/ul>\r\n\r\n<script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_0cac22f9bd604747b87ac53abaebbecf() {\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='0cac22f9bd604747b87ac53abaebbecf ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 0cac22f9bd604747b87ac53abaebbecf';\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 2011 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_0cac22f9bd604747b87ac53abaebbecf()\"><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.13<br><\/p>\r\n<\/div>\r\n<!--\r\n0cac22f9bd604747b87ac53abaebbecf ##### SOURCE BEGIN #####\r\n%%\r\n% Blog reader <https:\/\/blogs.mathworks.com\/steve\/2009\/01\/28\/have-you-heard-of-the-feature-transform\/#comment-24580 \r\n% Bogdan> asked this question last week:\r\n%\r\n% _I am trying to find the length and location of the shortest path between\r\n% objects. It seems like some application of bwdist should be able to do\r\n% this. Any advice? Example:_\r\n% \r\n%  1 0 1\r\n%  0 1 0\r\n%  0 0 0\r\n%  0 1 0\r\n%  1 0 1\r\n% \r\n% _Should yield_\r\n%\r\n%  0 0 0\r\n%  0 0 0\r\n%  0 p 0\r\n%  0 0 0\r\n%  0 0 0\r\n% \r\n% _With p = path length = 1_\r\n%\r\n% I agree, some application of |bwdist| should do it. Actually, there are\r\n% several other useful functions that can be applied to this task,\r\n% including |imregionalmin| and |bwdistgeodesic|, a new function that just\r\n% shipped in R2011b.\r\n%\r\n% I've been tinkering with this problem off and on for a few days, and I\r\n% think it might take a few posts to explore some of the interesting ideas\r\n% and issues posed by this problem. Today I'll start with the basics of\r\n% using |bwdist| and |imregionalmin| to identify a set of shortest paths\r\n% from one object to another.\r\n%\r\n% Let's use this simple test image to start our exploration.\r\n\r\nbw = [ ...\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0   ]\r\n\r\n%%\r\n% We want to find the shortest path (or paths!) from the upper left block\r\n% of foreground pixels to the lower right block. The key algorithmic idea\r\n% is this:\r\n%\r\n% # Compute the distance transform for just the upper left block of\r\n% foreground pixels.\r\n% # Compute the distance transform for just the lower right block of\r\n% foreground pixels.\r\n% # Add the two distance transforms together.\r\n% # The pixels in the regional minimum of the result lie along one or more\r\n% of the shortest paths from one block to the other.\r\n%\r\n% (For reference, see P. Soille, Morphological Image Analysis: Principles\r\n% and Applications, 2nd edition, Springer, 2003, section 7.3.4,\r\n% \"Application to minimal path detection,\" pp. 233-234.)\r\n%\r\n% But we can't use the normal Euclidean distance transform because it\r\n% doesn't correspond to a path traversal from one pixel center to another.\r\n% Rather, we have to use one of the distance transform approximations\r\n% supported by |bwdist|: |'chessboard'|, |'cityblock'|, and\r\n% |'quasi-euclidean'|.\r\n%\r\n% Here's how to do it using |'quasi-euclidean'|.\r\n\r\nbw1 = [ ...\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 1 1 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0   ];\r\n\r\nbw2 = [ ...\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 1 1 0\r\n    0 0 0 0 0 0 0 0 0 0 0 0   ];\r\n\r\nD1 = bwdist(bw1, 'quasi-euclidean');\r\nD2 = bwdist(bw2, 'quasi-euclidean');\r\n\r\nD_sum = D1 + D2;\r\nD_sum(3:5, 3:10)\r\n\r\n%%\r\n% You can see that the smallest value of |D_sum| is about 7.8284, and\r\n% there's a set of pixels in-between the two objects that all have that\r\n% value. The function |imregionalmin| identifies them all:\r\n\r\npath_pixels = imregionalmin(D_sum)\r\n\r\n%%\r\n% In the quasi-euclidean approximation to the distance transform, the\r\n% distance from a pixel to one of its horizontal or vertical neighbors is\r\n% 1, and the distance from a pixel to one of its diagonal neighbors is\r\n% sqrt(2). The result above says that the shortest such path between the\r\n% two objects is 7.8284. Furthermore, it says that there is more than one\r\n% shortest path.\r\n%\r\n% I plan to explore this topic more fully this month. When using the\r\n% quasi-euclidean distance transform, for example, there are floating-point\r\n% round-off issues that have to be dealt with when you try to apply the\r\n% technique above to larger images. Another issue is the effect of using\r\n% different path-based distance transform approximations, such as\r\n% |'cityblock'| or |'chessboard'|. Yet another issue is how to identify\r\n% specific paths from the family of paths identified by |imregionalmin|.\r\n% Along the way I'll experiment with different ways to visualize the\r\n% results.\r\n%\r\n% Finally, I'll explore how to use a new function, |bwdistgeodesic|, to\r\n% find shortest paths when there are constraints on where the paths can go.\r\n##### SOURCE END ##### 0cac22f9bd604747b87ac53abaebbecf\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   Blog reader Bogdan asked this question last week:\r\n   \r\n   I am trying to find the length and location of the shortest path between objects. It seems like some application of bwdist\r\n        ... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/11\/01\/exploring-shortest-paths-part-1\/\">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":[456,839,366],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/395"}],"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=395"}],"version-history":[{"count":3,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/395\/revisions"}],"predecessor-version":[{"id":3765,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/395\/revisions\/3765"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=395"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=395"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=395"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}