{"id":5859,"date":"2015-02-20T09:00:22","date_gmt":"2015-02-20T14:00:22","guid":{"rendered":"https:\/\/blogs.mathworks.com\/pick\/?p=5859"},"modified":"2015-02-22T20:04:34","modified_gmt":"2015-02-23T01:04:34","slug":"downsampling-polygons-part-2","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/pick\/2015\/02\/20\/downsampling-polygons-part-2\/","title":{"rendered":"Downsampling polygons (Part 2)"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p><a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/15007\">Jiro<\/a>'s pick this week is <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/34639-decimate-polygon\">Decimate Polygon<\/a> by <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/1500618\">Anton Semechko<\/a>.\r\n   <\/p>\r\n   <p>Just a little over a year ago, I wrote a blog post on <a href=\"https:\/\/blogs.mathworks.com\/pick\/2014\/02\/07\/downsampling-polygons\/\">downsampling polygons<\/a>. I highlighted Peter's <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/45342-polygon-simplification\">Polygon Simplification<\/a>. His entry helped me out in one of my side projects I was working on at the time. Soon after, I received an email from a\r\n      File Exchange contributor letting me know about another entry for accomplishing the task of downsampling polygons. I appreciate\r\n      people letting me know about these entries I've overlooked. When I select a file to highlight in my posts I try to do a search\r\n      on similar entries, but I don't always catch them all.\r\n   <\/p>\r\n   <p>Let's see how <tt>DecimatePoly<\/tt> works. I'm going to use the same image I used for my previous post.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">im = imread(<span style=\"color: #A020F0\">'amoeba.png'<\/span>);\r\nimshow(im)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/jiro\/potw_decimatepoly\/potw_decimatepoly_01.png\"> <p>As before, I will convert this to black and white and trace out the boundaries using <a href=\"https:\/\/www.mathworks.com\/help\/images\/ref\/bwboundaries.html\"><tt>bwboundaries<\/tt><\/a> from the <a href=\"https:\/\/www.mathworks.com\/products\/image\/\">Image Processing Toolbox<\/a>. Then I will overlay the largest boundary onto the original image.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">im2 = im2bw(im);\r\nboundaries = bwboundaries(~im2,<span style=\"color: #A020F0\">'noholes'<\/span>)\r\n\r\nlargest = boundaries{1};\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\nplot(largest(:,2),largest(:,1),<span style=\"color: #A020F0\">'r'<\/span>,<span style=\"color: #A020F0\">'LineWidth'<\/span>,2)\r\nhold <span style=\"color: #A020F0\">off<\/span><\/pre><pre style=\"font-style:oblique\">boundaries = \r\n    [1696x2 double]\r\n    [  30x2 double]\r\n    [  33x2 double]\r\n    [ 111x2 double]\r\n    [  31x2 double]\r\n    [  34x2 double]\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/jiro\/potw_decimatepoly\/potw_decimatepoly_02.png\"> <p>Currently, the boundary has 1696 vertices.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">size(largest)<\/pre><pre style=\"font-style:oblique\">ans =\r\n        1696           2\r\n<\/pre><p>With <tt>DecimatePoly<\/tt>, I can downsample this polygon by specifying either the maximum acceptable offset from the original boundary or the fraction\r\n      of the total number of points to retain. For example, if I want to ensure the downsampled boundary to be off by maximum of\r\n      .1 pixels,\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">b1 = DecimatePoly(largest, [.1 1]);<\/pre><pre style=\"font-style:oblique\">\t\t# of verts\t\tperimeter\t\tarea\r\nin\t\t1695 \t\t\t1948.91\t\t\t27992.50\r\nout\t\t926  \t\t\t1948.91\t\t\t27992.50\r\n-----------------------------------------------------\r\nchange\t-45.37%\t\t\t-0.00%\t\t\t0.00 %\r\n\r\n<\/pre><p>I can see that I have about 45% fewer points while maintaining the same perimeter and area. If I loosen my constraint,<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">b2 = DecimatePoly(largest, [1 1]);<\/pre><pre style=\"font-style:oblique\">\t\t# of verts\t\tperimeter\t\tarea\r\nin\t\t1695 \t\t\t1948.91\t\t\t27992.50\r\nout\t\t473  \t\t\t1863.07\t\t\t28046.00\r\n-----------------------------------------------------\r\nchange\t-72.09%\t\t\t-4.40%\t\t\t0.19 %\r\n\r\n<\/pre><p>I have over 70% fewer points while not sacrificing much change in perimeter or area.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">figure\r\nsubplot(1,2,1)\r\nplot(largest(:,2),largest(:,1))\r\naxis <span style=\"color: #A020F0\">image<\/span> <span style=\"color: #A020F0\">ij<\/span>\r\n\r\nsubplot(1,2,2)\r\nplot(b2(:,2),b2(:,1))\r\naxis <span style=\"color: #A020F0\">image<\/span> <span style=\"color: #A020F0\">ij<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/jiro\/potw_decimatepoly\/potw_decimatepoly_03.png\"> <p>So why is having fewer points preferred? Well, Anton has included a nice demo with his entry that shows improved performance\r\n      in in-polygon tests. This is one of the plots from the demo.\r\n   <\/p>\r\n   <p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/jiro\/potw_decimatepoly\/decimate_performance.png\"> <\/p>\r\n   <p>He looked at how different number of polygon points affected the computation time and the accuracy of in-polygon tests. The\r\n      horizontal axis (Percent simplification) represents the degree of downsampling. The lower the percent simplification, the\r\n      greater the downsampling. The <a href=\"http:\/\/en.wikipedia.org\/wiki\/S%C3%B8rensen%E2%80%93Dice_coefficient\">Dice coefficient<\/a> (blue) shows how similar the results are between the downsampled polygon and the full polygon. The closer the value is to\r\n      1, the more similar the results. The right axis (red) shows the relative speed up of the computation time compared to the\r\n      full polygon. We can see that even at around 10% simplification (downsampled by 90%), we are able to get over 98% similarity\r\n      and 10x speed up.\r\n   <\/p>\r\n   <p><b>Comments<\/b><\/p>\r\n   <p>Do you have a need to downsample polygons? What is your use case? Let us know <a href=\"https:\/\/blogs.mathworks.com\/pick\/?p=5859#respond\">here<\/a> or leave a <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/34639-decimate-polygon#comments\">comment<\/a> for Anton.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_e2a75cfdebed4f4d9a5be8ce178dd9e3() {\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='e2a75cfdebed4f4d9a5be8ce178dd9e3 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' e2a75cfdebed4f4d9a5be8ce178dd9e3';\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 = '';\r\n        copyright = 'Copyright 2015 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_e2a75cfdebed4f4d9a5be8ce178dd9e3()\"><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; R2014b<br><\/p>\r\n<\/div>\r\n<!--\r\ne2a75cfdebed4f4d9a5be8ce178dd9e3 ##### SOURCE BEGIN #####\r\n%%\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/authors\/15007\r\n% Jiro>'s pick this week is\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/34639-decimate-polygon Decimate\r\n% Polygon> by\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/profile\/authors\/1500618 Anton\r\n% Semechko>.\r\n%\r\n% Just a little over a year ago, I wrote a blog post on\r\n% <https:\/\/blogs.mathworks.com\/pick\/2014\/02\/07\/downsampling-polygons\/\r\n% downsampling polygons>. I highlighted Peter's\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/45342-polygon-simplification Polygon\r\n% Simplification>. His entry helped me out in one of my side projects I was\r\n% working on at the time. Soon after, I received an email from a File\r\n% Exchange contributor letting me know about another entry for\r\n% accomplishing the task of downsampling polygons. I appreciate people\r\n% letting me know about these entries I've overlooked. When I select a file\r\n% to highlight in my posts I try to do a search on similar entries, but I\r\n% don't always catch them all.\r\n%\r\n% Let's see how |DecimatePoly| works. I'm going to use the same image I\r\n% used for my previous post.\r\n\r\nim = imread('amoeba.png');\r\nimshow(im)\r\n\r\n%%\r\n% As before, I will convert this to black and white and trace out the\r\n% boundaries using\r\n% <https:\/\/www.mathworks.com\/help\/images\/ref\/bwboundaries.html\r\n% |bwboundaries|> from the <https:\/\/www.mathworks.com\/products\/image\/ Image\r\n% Processing Toolbox>. Then I will overlay the largest boundary onto the\r\n% original image.\r\n\r\nim2 = im2bw(im);\r\nboundaries = bwboundaries(~im2,'noholes')\r\n\r\nlargest = boundaries{1};\r\nhold on\r\nplot(largest(:,2),largest(:,1),'r','LineWidth',2)\r\nhold off\r\n\r\n%%\r\n% Currently, the boundary has 1696 vertices.\r\n\r\nsize(largest)\r\n\r\n%%\r\n% With |DecimatePoly|, I can downsample this polygon by specifying either\r\n% the maximum acceptable offset from the original boundary or the fraction\r\n% of the total number of points to retain. For example, if I want to ensure\r\n% the downsampled boundary to be off by maximum of .1 pixels,\r\n\r\nb1 = DecimatePoly(largest, [.1 1]);\r\n\r\n%%\r\n% I can see that I have about 45% fewer points while maintaining the same\r\n% perimeter and area. If I loosen my constraint,\r\n\r\nb2 = DecimatePoly(largest, [1 1]);\r\n\r\n%%\r\n% I have over 70% fewer points while not sacrificing much change in\r\n% perimeter or area.\r\n\r\nfigure\r\nsubplot(1,2,1)\r\nplot(largest(:,2),largest(:,1))\r\naxis image ij\r\n\r\nsubplot(1,2,2)\r\nplot(b2(:,2),b2(:,1))\r\naxis image ij\r\n\r\n%%\r\n% So why is having fewer points preferred? Well, Anton has included a nice\r\n% demo with his entry that shows improved performance in in-polygon tests.\r\n% This is one of the plots from the demo.\r\n%\r\n% <<decimate_performance.png>>\r\n%\r\n% He looked at how different number of polygon points affected the\r\n% computation time and the accuracy of in-polygon tests. The horizontal\r\n% axis (Percent simplification) represents the degree of downsampling. The\r\n% lower the percent simplification, the greater the downsampling. The\r\n% <http:\/\/en.wikipedia.org\/wiki\/S%C3%B8rensen%E2%80%93Dice_coefficient Dice\r\n% coefficient> (blue) shows how similar the results are between the\r\n% downsampled polygon and the full polygon. The closer the value is to 1,\r\n% the more similar the results. The right axis (red) shows the relative\r\n% speed up of the computation time compared to the full polygon. We can see\r\n% that even at around 10% simplification (downsampled by 90%), we are able\r\n% to get over 98% similarity and 10x speed up.\r\n%\r\n% *Comments*\r\n%\r\n% Do you have a need to downsample polygons? What is your use case? Let us\r\n% know <https:\/\/blogs.mathworks.com\/pick\/?p=5859#respond here> or leave a\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/34639-decimate-polygon#comments\r\n% comment> for Anton.\r\n\r\n##### SOURCE END ##### e2a75cfdebed4f4d9a5be8ce178dd9e3\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/pick\/jiro\/potw_decimatepoly\/potw_decimatepoly_01.png\" onError=\"this.style.display ='none';\" \/><\/div><p>\r\n   Jiro's pick this week is Decimate Polygon by Anton Semechko.\r\n   \r\n   Just a little over a year ago, I wrote a blog post on downsampling polygons. I highlighted Peter's Polygon Simplification.... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/pick\/2015\/02\/20\/downsampling-polygons-part-2\/\">read more >><\/a><\/p>","protected":false},"author":35,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[16],"tags":[],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/5859"}],"collection":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/users\/35"}],"replies":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/comments?post=5859"}],"version-history":[{"count":4,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/5859\/revisions"}],"predecessor-version":[{"id":5866,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/posts\/5859\/revisions\/5866"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/media?parent=5859"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/categories?post=5859"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/pick\/wp-json\/wp\/v2\/tags?post=5859"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}