{"id":337,"date":"2010-07-30T12:47:39","date_gmt":"2010-07-30T16:47:39","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2010\/07\/30\/visualizing-regionprops-ellipse-measurements\/"},"modified":"2019-10-29T13:32:16","modified_gmt":"2019-10-29T17:32:16","slug":"visualizing-regionprops-ellipse-measurements","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2010\/07\/30\/visualizing-regionprops-ellipse-measurements\/","title":{"rendered":"Visualizing regionprops ellipse measurements"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>The Image Processing Toolbox function <tt>regionprops<\/tt> gives you measurements of shape-based measurements of image regions. It's pretty useful, and I have shown many examples of\r\n      it on this blog. Today I want to show you how to visualize the ellipse-based measurements produced by <tt>regionprops<\/tt>.\r\n   <\/p>\r\n   <p>There are several supported measurements that are based on approximating regions by ellipses:<\/p>\r\n   <div>\r\n      <ul>\r\n         <li>Orientation<\/li>\r\n         <li>MajorAxisLength<\/li>\r\n         <li>MinorAxisLength<\/li>\r\n         <li>Eccentricity<\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <p>Here's an example.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">url = <span style=\"color: #A020F0\">'https:\/\/blogs.mathworks.com\/images\/steve\/2010\/rice_binary.png'<\/span>;\r\nbw = imread(url);\r\nimshow(bw)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/regionprops_ellipses_01.png\"> <p>Call <tt>regionprops<\/tt> with the list of measurements you desire:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s = regionprops(bw, <span style=\"color: #A020F0\">'Orientation'<\/span>, <span style=\"color: #A020F0\">'MajorAxisLength'<\/span>, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'MinorAxisLength'<\/span>, <span style=\"color: #A020F0\">'Eccentricity'<\/span>)<\/pre><pre style=\"font-style:oblique\">\r\ns = \r\n\r\n99x1 struct array with fields:\r\n    MajorAxisLength\r\n    MinorAxisLength\r\n    Eccentricity\r\n    Orientation\r\n\r\n<\/pre><p>From the output you can infer that <tt>regionprops<\/tt> found 99 objects in the binary image. It returned the desired measurements as a 99-element struct array. Here are the measurements\r\n      for the 10th object:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s(10)<\/pre><pre style=\"font-style:oblique\">\r\nans = \r\n\r\n    MajorAxisLength: 28.7693\r\n    MinorAxisLength: 9.4320\r\n       Eccentricity: 0.9447\r\n        Orientation: -27.0162\r\n\r\n<\/pre><p>How can you do a visual sanity check of the output? We should probably include some <tt>regionprops<\/tt> visualization utilities in the toolbox, but in the meantime I'll show you some code you can use to superimpose the fitted\r\n      ellipses over the original image.\r\n   <\/p>\r\n   <p>First, we'll one additional measurement: the centroid.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s = regionprops(bw, <span style=\"color: #A020F0\">'Orientation'<\/span>, <span style=\"color: #A020F0\">'MajorAxisLength'<\/span>, <span style=\"color: #0000FF\">...<\/span>\r\n    <span style=\"color: #A020F0\">'MinorAxisLength'<\/span>, <span style=\"color: #A020F0\">'Eccentricity'<\/span>, <span style=\"color: #A020F0\">'Centroid'<\/span>);<\/pre><p>For each ellipse, we'll use a parametric form of the ellipse equation to plot the outline of the ellipse over the image.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imshow(bw)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\n\r\nphi = linspace(0,2*pi,50);\r\ncosphi = cos(phi);\r\nsinphi = sin(phi);\r\n\r\n<span style=\"color: #0000FF\">for<\/span> k = 1:length(s)\r\n    xbar = s(k).Centroid(1);\r\n    ybar = s(k).Centroid(2);\r\n\r\n    a = s(k).MajorAxisLength\/2;\r\n    b = s(k).MinorAxisLength\/2;\r\n\r\n    theta = pi*s(k).Orientation\/180;\r\n    R = [ cos(theta)   sin(theta)\r\n         -sin(theta)   cos(theta)];\r\n\r\n    xy = [a*cosphi; b*sinphi];\r\n    xy = R*xy;\r\n\r\n    x = xy(1,:) + xbar;\r\n    y = xy(2,:) + ybar;\r\n\r\n    plot(x,y,<span style=\"color: #A020F0\">'r'<\/span>,<span style=\"color: #A020F0\">'LineWidth'<\/span>,2);\r\n<span style=\"color: #0000FF\">end<\/span>\r\nhold <span style=\"color: #A020F0\">off<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/regionprops_ellipses_02.png\"> <p>You can zoom in to see exactly why some of the ellipses don't seem to match objects in the image very well. Normally you'd\r\n      zoom interactively using the zoom controls in the figure toolbar, but of course I can't do that in this blog post, so I'll\r\n      use the <tt>axis<\/tt> function.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">axis([140 225 85 170])<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2010\/regionprops_ellipses_03.png\"> <p>Now you can see that the two objects in the center of the display are actually touching at one point. That caused <tt>regionprops<\/tt> to consider them to be a single object and to fit an ellipse to both of them together.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_61a751b47a564b5bbce8c56a29ed1c99() {\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='61a751b47a564b5bbce8c56a29ed1c99 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 61a751b47a564b5bbce8c56a29ed1c99';\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 2010 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_61a751b47a564b5bbce8c56a29ed1c99()\"><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.10<br><\/p>\r\n<\/div>\r\n<!--\r\n61a751b47a564b5bbce8c56a29ed1c99 ##### SOURCE BEGIN #####\r\n%%\r\n% The Image Processing Toolbox function |regionprops| gives you measurements\r\n% of shape-based measurements of image regions. It's pretty useful, and I\r\n% have shown many examples of it on this blog. Today I want to show you how\r\n% to visualize the ellipse-based measurements produced by |regionprops|.\r\n%\r\n% There are several supported measurements that are based on approximating\r\n% regions by ellipses:\r\n%\r\n% * Orientation\r\n% * MajorAxisLength\r\n% * MinorAxisLength\r\n% * Eccentricity\r\n%\r\n% Here's an example.\r\n\r\nurl = 'https:\/\/blogs.mathworks.com\/images\/steve\/2010\/rice_binary.png';\r\nbw = imread(url);\r\nimshow(bw)\r\n\r\n%%\r\n% Call |regionprops| with the list of measurements you desire:\r\n\r\ns = regionprops(bw, 'Orientation', 'MajorAxisLength', ...\r\n    'MinorAxisLength', 'Eccentricity')\r\n\r\n%%\r\n% From the output you can infer that |regionprops| found 99 objects in the\r\n% binary image. It returned the desired measurements as a 99-element struct\r\n% array. Here are the measurements for the 10th object:\r\n\r\ns(10)\r\n\r\n%%\r\n% How can you do a visual sanity check of the output? We should probably\r\n% include some |regionprops| visualization utilities in the toolbox, but in\r\n% the meantime I'll show you some code you can use to superimpose the\r\n% fitted ellipses over the original image.\r\n%\r\n% First, we'll one additional measurement: the centroid.\r\n\r\ns = regionprops(bw, 'Orientation', 'MajorAxisLength', ...\r\n    'MinorAxisLength', 'Eccentricity', 'Centroid');\r\n\r\n%%\r\n% For each ellipse, we'll use a parametric form of the ellipse equation to\r\n% plot the outline of the ellipse over the image.\r\n\r\nimshow(bw)\r\nhold on\r\n\r\nphi = linspace(0,2*pi,50);\r\ncosphi = cos(phi);\r\nsinphi = sin(phi);\r\n\r\nfor k = 1:length(s)\r\n    xbar = s(k).Centroid(1);\r\n    ybar = s(k).Centroid(2);\r\n    \r\n    a = s(k).MajorAxisLength\/2;\r\n    b = s(k).MinorAxisLength\/2;\r\n    \r\n    theta = pi*s(k).Orientation\/180;\r\n    R = [ cos(theta)   sin(theta)\r\n         -sin(theta)   cos(theta)];\r\n    \r\n    xy = [a*cosphi; b*sinphi];\r\n    xy = R*xy;\r\n    \r\n    x = xy(1,:) + xbar;\r\n    y = xy(2,:) + ybar;\r\n\r\n    plot(x,y,'r','LineWidth',2);\r\nend\r\nhold off\r\n\r\n%%\r\n% You can zoom in to see exactly why some of the ellipses don't seem to\r\n% match objects in the image very well. Normally you'd zoom interactively\r\n% using the zoom controls in the figure toolbar, but of course I can't do\r\n% that in this blog post, so I'll use the |axis| function.\r\n\r\naxis([140 225 85 170])\r\n\r\n%%\r\n% Now you can see that the two objects in the center of the display are\r\n% actually touching at one point. That caused |regionprops| to consider\r\n% them to be a single object and to fit an ellipse to both of them\r\n% together.\r\n##### SOURCE END ##### 61a751b47a564b5bbce8c56a29ed1c99\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   The Image Processing Toolbox function regionprops gives you measurements of shape-based measurements of image regions. It's pretty useful, and I have shown many examples of\r\n      it on this... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2010\/07\/30\/visualizing-regionprops-ellipse-measurements\/\">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,74,90,76,36,705,32,532,68,168,34],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/337"}],"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=337"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/337\/revisions"}],"predecessor-version":[{"id":3691,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/337\/revisions\/3691"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=337"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=337"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=337"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}