{"id":634,"date":"2012-07-06T11:57:20","date_gmt":"2012-07-06T15:57:20","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=634"},"modified":"2019-10-31T14:51:02","modified_gmt":"2019-10-31T18:51:02","slug":"walking-along-a-path","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2012\/07\/06\/walking-along-a-path\/","title":{"rendered":"Walking along a path"},"content":{"rendered":"<div class=\"content\"><!--introduction--><p>Last month I was experimenting with an algorithm in which I needed to construct a set of equidistant steps along a path consisting of line segments. (I'll call this a <i>polyline path<\/i>, or <i>polyline<\/i> for short.) Today I want to show you how to construct such a path in MATLAB. Along the way I'll show you the function <tt>improfile<\/tt> and give you a pointer to a database of sample range images that I found.<\/p><!--\/introduction--><h3>Contents<\/h3><div><ul><li><a href=\"#70443c69-c742-47d5-9956-a2d8fb3ec814\">Polylines<\/a><\/li><li><a href=\"#9b861267-61a4-4ae1-96b2-a2aadab5606b\">IMPROFILE<\/a><\/li><li><a href=\"#5d684ab6-0edb-4c52-8df2-4bce4a79ee80\">Computing equidistant steps along the polyline<\/a><\/li><\/ul><\/div><h4>Polylines<a name=\"70443c69-c742-47d5-9956-a2d8fb3ec814\"><\/a><\/h4><p>Here's a simple example of a polyline. (Note that, because we're going to be talking about distances, I'm going to set the aspect ratio of my plots to be 1:1 by calling <tt>axis equal<\/tt>.)<\/p><pre class=\"codeinput\">x = [24 214 327 617];\r\ny = [375 223 218 341];\r\nplot(x,y)\r\naxis <span class=\"string\">equal<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/polyline_path_01.png\" alt=\"\"> <p>This has three connected line segments. In this example, each segment has a different length. I wanted to be able to find a certain number of points that were equally spaced along this path.<\/p><h4>IMPROFILE<a name=\"9b861267-61a4-4ae1-96b2-a2aadab5606b\"><\/a><\/h4><p>After pondering this problem for a minute or so, I remembered that the function <tt>improfile<\/tt> does exactly this computation internally. The function <tt>improfile<\/tt> is used to compute pixel-value profiles along a user-specified polyline.<\/p><p>Let me illustrate <tt>improfile<\/tt> using a <i>range image<\/i>. In a range image, the pixel values represent estimated distance from the imaging device. I found the <a href=\"http:\/\/marathon.csee.usf.edu\/range\/DataBase.html\">USF (University of South Florida) Range Image Database<\/a> online. Below is a range image I downloaded from the database.  It was taken by the Vision Lab at USF using a \"K2T structured light camera.\" (No, I don't know what that is.) The web site helpfully tells me that the image is stored in \"rasterfile format,\" which is pretty dated but fortunately supported by <tt>imread<\/tt>.<\/p><pre class=\"codeinput\">url = <span class=\"string\">'https:\/\/blogs.mathworks.com\/images\/steve\/2012\/chessmen.range'<\/span>;\r\nI = imread(url, <span class=\"string\">'ras'<\/span>);\r\nimshow(I, <span class=\"string\">'InitialMagnification'<\/span>, 50)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/polyline_path_02.png\" alt=\"\"> <p>Let's use <tt>improfile<\/tt> to compute a cross-section of range values along a particular path. First, though, let me superimpose the path on the image so you can where it is. (Although <tt>improfile<\/tt> has an interactive mode that lets you select the path using a mouse, I can't show that here.)<\/p><pre class=\"codeinput\">hold <span class=\"string\">on<\/span>\r\nplot(x,y,<span class=\"string\">'r'<\/span>,<span class=\"string\">'LineWidth'<\/span>,5)\r\nhold <span class=\"string\">off<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/polyline_path_03.png\" alt=\"\"> <p>Here's the cross-section of range values.<\/p><pre class=\"codeinput\">improfile(I,x,y)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/polyline_path_04.png\" alt=\"\"> <p>You can see that <tt>improfile<\/tt> shows the cross-section as a 3-D plot. To see the cross-section as a normal 2-D line plot, call <tt>improfile<\/tt> with an output argument to get the cross-section values and then pass them to <tt>plot<\/tt>.<\/p><pre class=\"codeinput\">c = improfile(I,x,y);\r\nplot(c)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/polyline_path_05.png\" alt=\"\"> <h4>Computing equidistant steps along the polyline<a name=\"5d684ab6-0edb-4c52-8df2-4bce4a79ee80\"><\/a><\/h4><p>As part of its computation, <tt>improfile<\/tt> needs to compute equidistant steps along the polyline path. So how does that work?<\/p><p>The function first computes the cumulative distance from the beginning of the polyline to each vertex along the way, and then it uses a clever call to <tt>interp1<\/tt> to compute the steps.<\/p><pre class=\"codeinput\">xy = [x' y'];\r\nd = diff(xy,1)\r\n<\/pre><pre class=\"codeoutput\">\r\nd =\r\n\r\n   190  -152\r\n   113    -5\r\n   290   123\r\n\r\n<\/pre><pre class=\"codeinput\">dist_from_vertex_to_vertex = hypot(d(:,1), d(:,2))\r\n<\/pre><pre class=\"codeoutput\">\r\ndist_from_vertex_to_vertex =\r\n\r\n  243.3187\r\n  113.1106\r\n  315.0063\r\n\r\n<\/pre><pre class=\"codeinput\">cumulative_dist_along_path = [0;\r\n    cumsum(dist_from_vertex_to_vertex,1)]\r\n<\/pre><pre class=\"codeoutput\">\r\ncumulative_dist_along_path =\r\n\r\n         0\r\n  243.3187\r\n  356.4293\r\n  671.4356\r\n\r\n<\/pre><p>Now we can get our steps by constructing a call to <tt>interp1<\/tt>.<\/p><pre class=\"codeinput\">num_points = 20;\r\ndist_steps = linspace(0, cumulative_dist_along_path(end), num_points);\r\npoints = interp1(cumulative_dist_along_path, xy, dist_steps)\r\n<\/pre><pre class=\"codeoutput\">\r\npoints =\r\n\r\n   24.0000  375.0000\r\n   51.5949  352.9241\r\n   79.1898  330.8482\r\n  106.7847  308.7722\r\n  134.3796  286.6963\r\n  161.9745  264.6204\r\n  189.5694  242.5445\r\n  218.0483  222.8209\r\n  253.3525  221.2587\r\n  288.6567  219.6966\r\n  323.9609  218.1345\r\n  356.7328  230.6108\r\n  389.2662  244.4095\r\n  421.7996  258.2081\r\n  454.3330  272.0068\r\n  486.8664  285.8054\r\n  519.3998  299.6041\r\n  551.9332  313.4027\r\n  584.4666  327.2014\r\n  617.0000  341.0000\r\n\r\n<\/pre><p>Plot the points, superimposing them on the original path, to see how we did.<\/p><pre class=\"codeinput\">plot(x,y)\r\nhold <span class=\"string\">on<\/span>\r\nplot(points(:,1), points(:,2), <span class=\"string\">'o'<\/span>)\r\nhold <span class=\"string\">off<\/span>\r\naxis <span class=\"string\">equal<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2012\/polyline_path_06.png\" alt=\"\"> <p>There you go. Now you know about <tt>improfile<\/tt>, you know how to compute a path along a polyline, and you know about an online database of sample range imagery.<\/p><p>I think we should call it a day.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_cf4e22d9ae14485a938af7442b2810d4() {\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='cf4e22d9ae14485a938af7442b2810d4 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' cf4e22d9ae14485a938af7442b2810d4';\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        copyright = 'Copyright 2012 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 copyright line at the bottom if specified.\r\n        if (copyright.length > 0) {\r\n            d.writeln('');\r\n            d.writeln('%%');\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     --> <\/script><p style=\"text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray\"><br><a href=\"javascript:grabCode_cf4e22d9ae14485a938af7442b2810d4()\"><span style=\"font-size: x-small;        font-style: italic;\">Get \r\n      the MATLAB code <noscript>(requires JavaScript)<\/noscript><\/span><\/a><br><br>\r\n      Published with MATLAB&reg; 7.14<br><\/p><p class=\"footer\"><br>\r\n      Published with MATLAB&reg; 7.14<br><\/p><\/div><!--\r\ncf4e22d9ae14485a938af7442b2810d4 ##### SOURCE BEGIN #####\r\n%% Walking along a path\r\n% Last month I was experimenting with an algorithm in which I needed to\r\n% construct a set of equidistant steps along a path consisting of line\r\n% segments. (I'll call this a _polyline path_, or _polyline_ for short.)\r\n% Today I want to show you how to construct such a path in MATLAB. Along\r\n% the way I'll show you the function |improfile| and give you a pointer to\r\n% a database of sample range images that I found.\r\n%\r\n%% Polylines\r\n% Here's a simple example of a polyline. (Note that, because we're going to\r\n% be talking about distances, I'm going to set the aspect ratio of my plots\r\n% to be 1:1 by calling |axis equal|.)\r\n\r\nx = [24 214 327 617];\r\ny = [375 223 218 341];\r\nplot(x,y)\r\naxis equal\r\n\r\n%%\r\n% This has three connected line segments. In this example, each segment has\r\n% a different length. I wanted to be able to find a certain number of\r\n% points that were equally spaced along this path.\r\n\r\n%% IMPROFILE\r\n% After pondering this problem for a minute or so, I remembered that the\r\n% function |improfile| does exactly this computation internally. The\r\n% function |improfile| is used to compute pixel-value profiles along a\r\n% user-specified polyline.\r\n%\r\n% Let me illustrate |improfile| using a _range image_. In a range image,\r\n% the pixel values represent estimated distance from the imaging device. I\r\n% found the <http:\/\/marathon.csee.usf.edu\/range\/DataBase.html USF\r\n% (University of South Florida) Range Image Database> online. Below is a\r\n% range image I downloaded from the database.  It was taken by the Vision\r\n% Lab at USF using a \"K2T structured light camera.\" (No, I don't know what\r\n% that is.) The web site helpfully tells me that the image is stored in\r\n% \"rasterfile format,\" which is pretty dated but fortunately supported by\r\n% |imread|.\r\n\r\nurl = 'https:\/\/blogs.mathworks.com\/images\/steve\/2012\/chessmen.range';\r\nI = imread(url, 'ras');\r\nimshow(I, 'InitialMagnification', 50)\r\n\r\n%%\r\n% Let's use |improfile| to compute a cross-section of range values along a\r\n% particular path. First, though, let me superimpose the path on the image\r\n% so you can where it is. (Although |improfile| has an interactive mode\r\n% that lets you select the path using a mouse, I can't show that here.)\r\n\r\nhold on\r\nplot(x,y,'r','LineWidth',5)\r\nhold off\r\n\r\n%%\r\n% Here's the cross-section of range values.\r\n\r\nimprofile(I,x,y)\r\n\r\n%%\r\n% You can see that |improfile| shows the cross-section as a 3-D plot. To\r\n% see the cross-section as a normal 2-D line plot, call |improfile| with an\r\n% output argument to get the cross-section values and then pass them to\r\n% |plot|.\r\n\r\nc = improfile(I,x,y);\r\nplot(c)\r\n\r\n%% Computing equidistant steps along the polyline\r\n% As part of its computation, |improfile| needs to compute equidistant\r\n% steps along the polyline path. So how does that work?\r\n%\r\n% The function first computes the cumulative distance from the beginning of\r\n% the polyline to each vertex along the way, and then it uses a clever call\r\n% to |interp1| to compute the steps.\r\nxy = [x' y'];\r\nd = diff(xy,1)\r\n\r\n%%\r\ndist_from_vertex_to_vertex = hypot(d(:,1), d(:,2))\r\n\r\n%%\r\ncumulative_dist_along_path = [0;\r\n    cumsum(dist_from_vertex_to_vertex,1)]\r\n\r\n%%\r\n% Now we can get our steps by constructing a call to |interp1|.\r\nnum_points = 20;\r\ndist_steps = linspace(0, cumulative_dist_along_path(end), num_points);\r\npoints = interp1(cumulative_dist_along_path, xy, dist_steps)\r\n\r\n%%\r\n% Plot the points, superimposing them on the original path, to see how we\r\n% did.\r\nplot(x,y)\r\nhold on\r\nplot(points(:,1), points(:,2), 'o')\r\nhold off\r\naxis equal\r\n\r\n%%\r\n% There you go. Now you know about |improfile|, you know how to compute a\r\n% path along a polyline, and you know about an online database of sample\r\n% range imagery.\r\n%\r\n% I think we should call it a day.\r\n##### SOURCE END ##### cf4e22d9ae14485a938af7442b2810d4\r\n-->","protected":false},"excerpt":{"rendered":"<!--introduction--><p>Last month I was experimenting with an algorithm in which I needed to construct a set of equidistant steps along a path consisting of line segments. (I'll call this a <i>polyline path<\/i>, or <i>polyline<\/i> for short.) Today I want to show you how to construct such a path in MATLAB. Along the way I'll show you the function <tt>improfile<\/tt> and give you a pointer to a database of sample range images that I found.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2012\/07\/06\/walking-along-a-path\/\">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":[50,128,695,90,334,905,76,36,723,32,68],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/634"}],"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=634"}],"version-history":[{"count":5,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/634\/revisions"}],"predecessor-version":[{"id":3789,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/634\/revisions\/3789"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=634"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=634"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=634"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}