{"id":392,"date":"2011-09-30T07:00:12","date_gmt":"2011-09-30T11:00:12","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2011\/09\/30\/binary-image-convex-hull\/"},"modified":"2019-10-29T16:56:06","modified_gmt":"2019-10-29T20:56:06","slug":"binary-image-convex-hull","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2011\/09\/30\/binary-image-convex-hull\/","title":{"rendered":"Binary image convex hull"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>I've been intending to mention a new function <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/images\/ref\/bwconvhull.html\"><tt>bwconvhull<\/tt><\/a> that was introduced in the Image Processing Toolbox last spring in the R2011a release. Now that R2011b is out, I figure I\r\n      better go ahead and do it!\r\n   <\/p>\r\n   <p><tt>bwconvhull<\/tt> computes the \"convex hull of a binary image.\" Now I have to admit that this terminology is a little loose, so I'd better\r\n      clarify. The convex hull of a set of 2-D points is the smallest convex polygon that contains the entire set. Here's an example\r\n      from the MATLAB documentation for <a href=\"https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/convhull.html\"><tt>convhull<\/tt><\/a>:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">xx = -1:.05:1; yy = abs(sqrt(xx));\r\n[x,y] = pol2cart(xx,yy);\r\nk = convhull(x,y);\r\nplot(x(k),y(k),<span style=\"color: #A020F0\">'r-'<\/span>,x,y,<span style=\"color: #A020F0\">'b+'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_01.png\"> <p>The polygon in red is the convex hull of the set of points shown in blue. So <tt>convhull<\/tt> takes a set of points and returns a polygon, whereas <tt>bwconvhull<\/tt> takes a binary image and returns another binary image. What's up with that? It means simply that <tt>bwconvhull<\/tt> computes the convex hull of all the foreground pixels in the input image, and then it produces an output binary image with\r\n      all the pixels inside the convex hull set to white. It's a little easier to show than to say, so here's what it looks like:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = imread(<span style=\"color: #A020F0\">'text.png'<\/span>);\r\nimshow(bw)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_02.png\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw2 = bwconvhull(bw);\r\nimshow(bw2);<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_03.png\"> <p>Let's overlay the foreground pixel locations from the input image (using blue dots) and the convex hull computed by <tt>convhull<\/tt> (using a thick red line).\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[y, x] = find(bw);\r\nk = convhull(x, y);\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\nplot(x, y, <span style=\"color: #A020F0\">'b.'<\/span>)\r\nplot(x(k), y(k), <span style=\"color: #A020F0\">'r'<\/span>, <span style=\"color: #A020F0\">'LineWidth'<\/span>, 4)\r\nhold <span style=\"color: #A020F0\">off<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_04.png\"> <p>An important variation supported by <tt>bwconvhull<\/tt> is to compute the convex hulls of the individual objects in the input image. Here's how you do that:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw3 = bwconvhull(bw, <span style=\"color: #A020F0\">'objects'<\/span>);\r\nimshow(bw3)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_05.png\"> <p>Something called the <i>convex deficiency<\/i> is sometimes used in shape recognition applications. Loosely speaking, the convex deficiency of a shape is the convex hull\r\n      of the shape minus the shape. Here's an example using the letter \"T\" from the text image above.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bwt = bw(7:24, 4:18);\r\nimshow(bwt, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_06.png\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bwtc = bwconvhull(bw_t);\r\nimshow(bwtc, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)\r\ntitle(<span style=\"color: #A020F0\">'Convex hull image'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_07.png\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bwtcd = bwtc &amp; ~bwt;\r\nimshow(bwtcd, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, <span style=\"color: #A020F0\">'fit'<\/span>)\r\ntitle(<span style=\"color: #A020F0\">'Convex deficiency image'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/bwconvhull_example_08.png\"> <p>The convex deficiency of the letter \"T\" has two connected components. This kind of measurement can be useful for recognizing\r\n      shapes.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_5f4b348dae87475aa4b3f02f00cbfb64() {\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='5f4b348dae87475aa4b3f02f00cbfb64 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 5f4b348dae87475aa4b3f02f00cbfb64';\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_5f4b348dae87475aa4b3f02f00cbfb64()\"><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\n5f4b348dae87475aa4b3f02f00cbfb64 ##### SOURCE BEGIN #####\r\n%%\r\n% I've been intending to mention a new function\r\n% <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/toolbox\/images\/ref\/bwconvhull.html\r\n% |bwconvhull|> that was introduced in the Image Processing Toolbox last\r\n% spring in the R2011a release. Now that R2011b is out, I figure I better\r\n% go ahead and do it!\r\n%\r\n% |bwconvhull| computes the \"convex hull of a binary image.\" Now I have to\r\n% admit that this terminology is a little loose, so I'd better clarify. The\r\n% convex hull of a set of 2-D points is the smallest convex polygon that\r\n% contains the entire set. Here's an example from the MATLAB documentation\r\n% for <https:\/\/www.mathworks.com\/help\/releases\/R2011b\/techdoc\/ref\/convhull.html |convhull|>:\r\n\r\nxx = -1:.05:1; yy = abs(sqrt(xx));\r\n[x,y] = pol2cart(xx,yy);\r\nk = convhull(x,y);\r\nplot(x(k),y(k),'r-',x,y,'b+')\r\n\r\n%%\r\n% The polygon in red is the convex hull of the set of points shown in blue.\r\n% So |convhull| takes a set of points and returns a polygon, whereas\r\n% |bwconvhull| takes a binary image and returns another binary image.\r\n% What's up with that? It means simply that |bwconvhull| computes the\r\n% convex hull of all the foreground pixels in the input image, and then it\r\n% produces an output binary image with all the pixels inside the convex\r\n% hull set to white. It's a little easier to show than to say, so here's\r\n% what it looks like:\r\n\r\nbw = imread('text.png');\r\nimshow(bw)\r\n\r\n%%\r\nbw2 = bwconvhull(bw);\r\nimshow(bw2);\r\n\r\n%%\r\n% Let's overlay the foreground pixel locations from the input image (using\r\n% blue dots) and the convex hull computed by |convhull| (using a thick red\r\n% line).\r\n\r\n[y, x] = find(bw);\r\nk = convhull(x, y);\r\nhold on\r\nplot(x, y, 'b.')\r\nplot(x(k), y(k), 'r', 'LineWidth', 4)\r\nhold off\r\n\r\n%%\r\n% An important variation supported by |bwconvhull| is to compute the convex\r\n% hulls of the individual objects in the input image. Here's how you do\r\n% that:\r\n\r\nbw3 = bwconvhull(bw, 'objects');\r\nimshow(bw3)\r\n\r\n%%\r\n% Something called the _convex deficiency_ is sometimes used in shape\r\n% recognition applications. Loosely speaking, the convex deficiency of a\r\n% shape is the convex hull of the shape minus the shape. Here's an example\r\n% using the letter \"T\" from the text image above.\r\n\r\nbwt = bw(7:24, 4:18);\r\nimshow(bwt, 'InitialMagnification', 'fit')\r\n\r\n%%\r\n\r\nbwtc = bwconvhull(bw_t);\r\nimshow(bwtc, 'InitialMagnification', 'fit')\r\ntitle('Convex hull image')\r\n\r\n%%\r\n\r\nbwtcd = bwtc & ~bwt;\r\nimshow(bwtcd, 'InitialMagnification', 'fit')\r\ntitle('Convex deficiency image')\r\n\r\n%%\r\n% The convex deficiency of the letter \"T\" has two connected components.\r\n% This kind of measurement can be useful for recognizing shapes.\r\n\r\n\r\n##### SOURCE END ##### 5f4b348dae87475aa4b3f02f00cbfb64\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   I've been intending to mention a new function bwconvhull that was introduced in the Image Processing Toolbox last spring in the R2011a release. Now that R2011b is out, I figure I\r\n      better... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/09\/30\/binary-image-convex-hull\/\">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":[208,837,835,348,90,76,36,68,833,194,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/392"}],"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=392"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/392\/revisions"}],"predecessor-version":[{"id":3759,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/392\/revisions\/3759"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=392"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=392"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=392"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}