{"id":1401,"date":"2015-08-17T16:22:30","date_gmt":"2015-08-17T20:22:30","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=1401"},"modified":"2019-11-01T11:45:42","modified_gmt":"2019-11-01T15:45:42","slug":"ellipse-visualization-and-regionprops","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2015\/08\/17\/ellipse-visualization-and-regionprops\/","title":{"rendered":"Ellipse visualization and regionprops"},"content":{"rendered":"<div class=\"content\"><p>A blog reader asked me recently how to visualize the ellipse-based measurements computed by <a href=\"https:\/\/www.mathworks.com\/help\/images\/ref\/regionprops.html\"><tt>regionprops<\/tt><\/a>. The reader wanted to superimpose the estimated ellipses on the image.<\/p><p>To refresh your memory: The function <tt>regionprops<\/tt>, which computes geometrical measurements of image regions, offers several measurements that are based on fitting an ellipse to the region. (If you must know, the ellipse fit is computing by matching second-order moments.) These measurements are:<\/p><div><ul><li>MajorAxisLength<\/li><li>MinorAxisLength<\/li><li>Orientation<\/li><\/ul><\/div><p>I would plot an ellipse using a parametric equation. Conveniently, the <a href=\"https:\/\/en.wikipedia.org\/wiki\/Ellipse\">Wikipedia article on ellipses<\/a> has a parametric equation in a form that's just right:<\/p><p>$$X(t) = X_c + a \\cos t \\cos \\phi - b \\sin t \\sin \\phi$$<\/p><p>$$Y(t) = Y_c + a \\cos t \\sin \\phi + b \\sin t \\cos \\phi$$<\/p><p>where $(X_c,Y_c)$ is the ellipse center, $a$ and $b$ are the major and minor axis lengths, and $\\phi$ is the angle between the x-axis and the major axis.<\/p><p>Let's try it with this image, which contains a bunch of ellipse-like objects:<\/p><pre class=\"codeinput\">url = <span class=\"string\">'https:\/\/blogs.mathworks.com\/steve\/files\/rice-bw.png'<\/span>;\r\nbw = imread(url);\r\nimshow(bw)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/ellipse_lines_01.png\" alt=\"\"> <p>Ask <tt>regionprops<\/tt> to compute all the ellipse-related measurements:<\/p><pre class=\"codeinput\">s = regionprops(bw,{<span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">'Centroid'<\/span>,<span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">'MajorAxisLength'<\/span>,<span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">'MinorAxisLength'<\/span>,<span class=\"keyword\">...<\/span>\r\n    <span class=\"string\">'Orientation'<\/span>})\r\n<\/pre><pre class=\"codeoutput\">\r\ns = \r\n\r\n69x1 struct array with fields:\r\n\r\n    Centroid\r\n    MajorAxisLength\r\n    MinorAxisLength\r\n    Orientation\r\n\r\n<\/pre><p>Here's what the measurements look like for the seventh object:<\/p><pre class=\"codeinput\">s(7)\r\n<\/pre><pre class=\"codeoutput\">\r\nans = \r\n\r\n           Centroid: [37.9286 226.9732]\r\n    MajorAxisLength: 30.9655\r\n    MinorAxisLength: 9.7466\r\n        Orientation: -64.8058\r\n\r\n<\/pre><p>Now write a loop that computes the ellipse curves one at a time, for each object, and superimposes the curve on the image.<\/p><pre class=\"codeinput\">figure\r\nimshow(bw,<span class=\"string\">'InitialMagnification'<\/span>,<span class=\"string\">'fit'<\/span>)\r\n\r\nt = linspace(0,2*pi,50);\r\n\r\nhold <span class=\"string\">on<\/span>\r\n<span class=\"keyword\">for<\/span> k = 1:length(s)\r\n    a = s(k).MajorAxisLength\/2;\r\n    b = s(k).MinorAxisLength\/2;\r\n    Xc = s(k).Centroid(1);\r\n    Yc = s(k).Centroid(2);\r\n    phi = deg2rad(-s(k).Orientation);\r\n    x = Xc + a*cos(t)*cos(phi) - b*sin(t)*sin(phi);\r\n    y = Yc + a*cos(t)*sin(phi) + b*sin(t)*cos(phi);\r\n    plot(x,y,<span class=\"string\">'r'<\/span>,<span class=\"string\">'Linewidth'<\/span>,5)\r\n<span class=\"keyword\">end<\/span>\r\nhold <span class=\"string\">off<\/span>\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/ellipse_lines_02.png\" alt=\"\"> <p>That's it!<\/p><p>Enjoy.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_097d844e16914f228cb6f4c0d2dc7a43() {\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='097d844e16914f228cb6f4c0d2dc7a43 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 097d844e16914f228cb6f4c0d2dc7a43';\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 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 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_097d844e16914f228cb6f4c0d2dc7a43()\"><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; R2015a<br><\/p><\/div><!--\r\n097d844e16914f228cb6f4c0d2dc7a43 ##### SOURCE BEGIN #####\r\n%%\r\n% A blog reader asked me recently how to visualize the ellipse-based\r\n% measurements computed by\r\n% <https:\/\/www.mathworks.com\/help\/images\/ref\/regionprops.html |regionprops|>. The\r\n% reader wanted to superimpose the estimated ellipses on the image.\r\n%\r\n% To refresh your memory: The function |regionprops|, which computes geometrical\r\n% measurements of image regions, offers several measurements that are based on\r\n% fitting an ellipse to the region. (If you must know, the ellipse fit is\r\n% computing by matching second-order moments.) These measurements are:\r\n%\r\n% * MajorAxisLength\r\n% * MinorAxisLength\r\n% * Orientation\r\n%\r\n% I would plot an ellipse using a parametric equation. Conveniently, the\r\n% <https:\/\/en.wikipedia.org\/wiki\/Ellipse Wikipedia article on ellipses> has a\r\n% parametric equation in a form that's just right:\r\n%\r\n% $$X(t) = X_c + a \\cos t \\cos \\phi - b \\sin t \\sin \\phi$$\r\n%\r\n% $$Y(t) = Y_c + a \\cos t \\sin \\phi + b \\sin t \\cos \\phi$$\r\n%\r\n% where $(X_c,Y_c)$ is the ellipse center, $a$ and $b$ are the major and minor\r\n% axis lengths, and $\\phi$ is the angle between the x-axis and the major axis.\r\n%\r\n% Let's try it with this image, which contains a bunch of ellipse-like objects:\r\n\r\nurl = 'https:\/\/blogs.mathworks.com\/steve\/files\/rice-bw.png';\r\nbw = imread(url);\r\nimshow(bw)\r\n\r\n%%\r\n% Ask |regionprops| to compute all the ellipse-related measurements:\r\n\r\ns = regionprops(bw,{...\r\n    'Centroid',...\r\n    'MajorAxisLength',...\r\n    'MinorAxisLength',...\r\n    'Orientation'})\r\n\r\n%%\r\n% Here's what the measurements look like for the seventh object:\r\n\r\ns(7)\r\n\r\n%%\r\n% Now write a loop that computes the ellipse curves one at a time, for each\r\n% object, and superimposes the curve on the image.\r\n\r\nfigure\r\nimshow(bw,'InitialMagnification','fit')\r\n\r\nt = linspace(0,2*pi,50);\r\n\r\nhold on\r\nfor k = 1:length(s)\r\n    a = s(k).MajorAxisLength\/2;\r\n    b = s(k).MinorAxisLength\/2;\r\n    Xc = s(k).Centroid(1);\r\n    Yc = s(k).Centroid(2);\r\n    phi = deg2rad(-s(k).Orientation);\r\n    x = Xc + a*cos(t)*cos(phi) - b*sin(t)*sin(phi);\r\n    y = Yc + a*cos(t)*sin(phi) + b*sin(t)*cos(phi);\r\n    plot(x,y,'r','Linewidth',5)\r\nend\r\nhold off\r\n\r\n%%\r\n% That's it!\r\n%\r\n% Enjoy.\r\n    \r\n##### SOURCE END ##### 097d844e16914f228cb6f4c0d2dc7a43\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/steve\/files\/ellipse_lines_02.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><p>A blog reader asked me recently how to visualize the ellipse-based measurements computed by regionprops. The reader wanted to superimpose the estimated ellipses on the image.To refresh your memory:... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2015\/08\/17\/ellipse-visualization-and-regionprops\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":1394,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[74,1121,725,90,76,36,705,32,68,168,34],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1401"}],"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=1401"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1401\/revisions"}],"predecessor-version":[{"id":1402,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/1401\/revisions\/1402"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media\/1394"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=1401"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=1401"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=1401"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}