{"id":974,"date":"2014-02-04T13:28:43","date_gmt":"2014-02-04T18:28:43","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=974"},"modified":"2019-11-01T10:59:24","modified_gmt":"2019-11-01T14:59:24","slug":"regionprops-tables-and-struct2table","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2014\/02\/04\/regionprops-tables-and-struct2table\/","title":{"rendered":"regionprops, tables, and struct2table"},"content":{"rendered":"<div class=\"content\"><p>Today I was talking to Spandan (a regular guest blogger here) about the history of the Image Processing Toolbox function <tt>regionprops<\/tt>. This function is a widely-used work-horse of the toolbox. Many of my blog posts here have shown it in practice.<\/p><p>The function <tt>regionprops<\/tt> computes properties of regions of pixels. Most often, these regions correspond to individual \"objects\" (connected components of foreground pixels) of a binary image. Here's an example.<\/p><pre class=\"codeinput\">bw = imread(<span class=\"string\">'text.png'<\/span>);\r\nimshow(bw)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/regionprops_table_01.png\" alt=\"\"> <pre class=\"codeinput\">s = regionprops(bw)\r\n<\/pre><pre class=\"codeoutput\">\r\ns = \r\n\r\n88x1 struct array with fields:\r\n\r\n    Area\r\n    Centroid\r\n    BoundingBox\r\n\r\n<\/pre><p>The output is an 88x1 struct array, elements of which contain measurements for objects in the binary image. (We didn't tell <tt>regionprops<\/tt> what measurements to compute, so it computed Area, Centroid, and BoundingBox by default.) Here are the measurements for the 10th object.<\/p><pre class=\"codeinput\">s(10)\r\n<\/pre><pre class=\"codeoutput\">\r\nans = \r\n\r\n           Area: 61\r\n       Centroid: [54 39]\r\n    BoundingBox: [49.5000 33.5000 9 11]\r\n\r\n<\/pre><p>This form of output is convenient in some ways but inconvenient or awkward in others. For example, it requires the obscure \"comma-separated-list\" syntax to get all the area measurements into a single vector to call a function such as <tt>mean<\/tt>, <tt>min<\/tt>, or <tt>max<\/tt>.<\/p><pre class=\"codeinput\">a = [s.Area];\r\nmean(a)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n   54.2386\r\n\r\n<\/pre><pre class=\"codeinput\">min(a)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n     6\r\n\r\n<\/pre><pre class=\"codeinput\">max(a)\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n   106\r\n\r\n<\/pre><p>In the comma-separated list syntax for struct arrays, the expression <tt>[s.Area]<\/tt> automatically expands into the expression <tt>[s(1).Area, s(2).Area, ..., s(end).Area]<\/tt>. But relatively few people recognize or understand this syntax.<\/p><p>Another inconvenient aspect of the struct array aspect is that it's hard to get a tabular view of all the data. As shown above, you can see the data for the 10th object by displaying <tt>s(10)<\/tt>, but it's hard to see all the data for multiple objects. For example:<\/p><pre class=\"codeinput\">s(1:5)\r\n<\/pre><pre class=\"codeoutput\">\r\nans = \r\n\r\n5x1 struct array with fields:\r\n\r\n    Area\r\n    Centroid\r\n    BoundingBox\r\n\r\n<\/pre><p>If I were designing <tt>regionprops<\/tt> from scratch today, based on the most recent version of MATLAB, I would have <tt>regionprops<\/tt> return a <tt>table<\/tt>. Tables were introduced as a new fundamental MATLAB type in R2013b. Here's a simple example to illustrate.<\/p><pre class=\"codeinput\">age = [38 43 38 40 49]';\r\nheight = [71 69 64 67 64]';\r\nweight = [176 163 131 133 119]';\r\nblood_pressure = [124 93; 109 77; 125 83; 117 75; 122 80];\r\nt = table(age,height,weight,blood_pressure)\r\n<\/pre><pre class=\"codeoutput\">\r\nt = \r\n\r\n    age    height    weight    blood_pressure \r\n    ___    ______    ______    _______________\r\n\r\n    38     71        176       124          93\r\n    43     69        163       109          77\r\n    38     64        131       125          83\r\n    40     67        133       117          75\r\n    49     64        119       122          80\r\n\r\n<\/pre><p><tt>t.height<\/tt> is an ordinary 5-by-1 vector of heights.<\/p><pre class=\"codeinput\">t.height\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n    71\r\n    69\r\n    64\r\n    67\r\n    64\r\n\r\n<\/pre><p><tt>t.blood_pressure<\/tt> is an ordinary 5-by-2 matrix. (Table \"variables\" are often column vectors, but they can have any size as long as the number of rows is the same as the height of the table.)<\/p><pre class=\"codeinput\">t.blood_pressure\r\n<\/pre><pre class=\"codeoutput\">\r\nans =\r\n\r\n   124    93\r\n   109    77\r\n   125    83\r\n   117    75\r\n   122    80\r\n\r\n<\/pre><p>We are excited about the introduction of tables in MATLAB, and we think they will gradually be used in more and more situations where previously people used struct arrays.<\/p><p>Such as <tt>regionprops<\/tt>.<\/p><p>So what to do?<\/p><p>Well, the function <tt>struct2table<\/tt> comes in very handy here! As you might have guessed from the name, it automatically converts a struct array into a table.<\/p><p>Try it:<\/p><pre class=\"codeinput\">t = struct2table(s)\r\n<\/pre><pre class=\"codeoutput\">\r\nt = \r\n\r\n    Area         Centroid         BoundingBox \r\n    ____    __________________    ____________\r\n\r\n     66         11        13.5    [1x4 double]\r\n     41     7.6829      38.171    [1x4 double]\r\n     63     17.889      38.857    [1x4 double]\r\n     80      22.95      15.963    [1x4 double]\r\n     53     26.472      36.604    [1x4 double]\r\n     63     34.889      16.857    [1x4 double]\r\n     63     34.889      38.857    [1x4 double]\r\n     41     43.683      38.171    [1x4 double]\r\n     48     48.396      15.875    [1x4 double]\r\n     61         54          39    [1x4 double]\r\n     63     56.889      16.857    [1x4 double]\r\n     41     65.683      16.171    [1x4 double]\r\n     48     67.396      37.875    [1x4 double]\r\n    105      78.79       16.79    [1x4 double]\r\n     66       76.5          39    [1x4 double]\r\n     68     93.529      39.265    [1x4 double]\r\n     92        100      16.696    [1x4 double]\r\n     41     106.68      38.171    [1x4 double]\r\n     68     113.53      17.265    [1x4 double]\r\n      6        114        31.5    [1x4 double]\r\n     33        114          39    [1x4 double]\r\n     85     123.24      38.259    [1x4 double]\r\n     48      121.4      15.875    [1x4 double]\r\n     63     129.89      16.857    [1x4 double]\r\n    100     134.87       40.86    [1x4 double]\r\n     41     138.68      16.171    [1x4 double]\r\n     63     145.89      38.857    [1x4 double]\r\n     61        149          17    [1x4 double]\r\n     80     159.95      15.963    [1x4 double]\r\n     85     163.26      185.76    [1x4 double]\r\n      6      156.5         195    [1x4 double]\r\n      6      156.5         211    [1x4 double]\r\n     85     163.26      218.76    [1x4 double]\r\n     48      159.4      37.875    [1x4 double]\r\n     61        164         107    [1x4 double]\r\n     68     164.26      117.47    [1x4 double]\r\n     63     163.86      129.11    [1x4 double]\r\n     41     163.17      139.32    [1x4 double]\r\n     68     164.26      147.47    [1x4 double]\r\n     61        164         164    [1x4 double]\r\n     63     163.86      175.11    [1x4 double]\r\n     33        164         195    [1x4 double]\r\n     54     163.44         203    [1x4 double]\r\n     33        164         211    [1x4 double]\r\n     80     167.95      37.962    [1x4 double]\r\n      9        168         233    [1x4 double]\r\n      9        168         238    [1x4 double]\r\n      9        168         243    [1x4 double]\r\n     63     171.89      16.857    [1x4 double]\r\n     68     180.53      39.265    [1x4 double]\r\n     48     184.88      67.604    [1x4 double]\r\n    106      183.6      118.53    [1x4 double]\r\n      6      178.5         127    [1x4 double]\r\n     85     185.26      134.76    [1x4 double]\r\n     85     185.26      164.24    [1x4 double]\r\n     85     185.26      179.76    [1x4 double]\r\n      6      178.5         212    [1x4 double]\r\n     85     185.26      238.76    [1x4 double]\r\n     85     184.24      16.259    [1x4 double]\r\n     72     185.68      76.653    [1x4 double]\r\n     63     185.86      88.111    [1x4 double]\r\n     41     185.17      98.317    [1x4 double]\r\n     63     185.86      107.11    [1x4 double]\r\n     33        186         127    [1x4 double]\r\n     74      187.2      152.31    [1x4 double]\r\n     63     185.86      192.11    [1x4 double]\r\n     72     185.68      203.65    [1x4 double]\r\n     33        186         212    [1x4 double]\r\n     68     186.26      219.47    [1x4 double]\r\n     41     185.17      230.32    [1x4 double]\r\n     48      188.4      37.875    [1x4 double]\r\n      9        199          43    [1x4 double]\r\n     48     206.88       161.6    [1x4 double]\r\n      6      200.5         235    [1x4 double]\r\n      9        204          43    [1x4 double]\r\n     61        208         125    [1x4 double]\r\n    105     207.79      139.21    [1x4 double]\r\n     63     207.86      153.11    [1x4 double]\r\n     61        208         170    [1x4 double]\r\n     74      209.2      181.31    [1x4 double]\r\n     61        208         192    [1x4 double]\r\n     41     207.17      207.32    [1x4 double]\r\n     63     207.86      216.11    [1x4 double]\r\n     54     207.44         227    [1x4 double]\r\n     33        208         235    [1x4 double]\r\n     41     207.17      242.32    [1x4 double]\r\n      9        209          43    [1x4 double]\r\n      9        212         117    [1x4 double]\r\n\r\n<\/pre><p>Immediately, you can see that the data is much more easily visible with a table. You get scrolling and editing if you open <tt>t<\/tt> in the Variable Editor.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/table-variable-editor-screen-shot.png\" alt=\"\"> <\/p><p>You can plot directly with the data in a table variable:<\/p><pre class=\"codeinput\">imshow(bw)\r\nhold <span class=\"string\">on<\/span>\r\nplot(t.Centroid(:,1),t.Centroid(:,2),<span class=\"string\">'r*'<\/span>)\r\naxis([.5 100.5 .5 100.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\/2014\/regionprops_table_02.png\" alt=\"\"> <p>Logical indexing comes in handy for filtering objects based on various criteria. For example, the following code removes objects with area less than 10 from the table.<\/p><pre class=\"codeinput\">t(t.Area &lt; 10,:) = [];\r\n<\/pre><p>And you can easily export tables to various formats. Here is our table exported to a .CSV file and then read into Excel.<\/p><pre class=\"codeinput\">writetable(t,<span class=\"string\">'regionprops.csv'<\/span>);\r\n<\/pre><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/excel-screen-shot.png\" alt=\"\"> <\/p><p>I encourage everyone who has used <tt>regionprops<\/tt> to play around with tables (assuming you have MATLAB R2013b) to see how they might be useful in your own work.<\/p><script language=\"JavaScript\"> <!-- \r\n    function grabCode_29721cd719b34f8db371bed9470ed40d() {\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='29721cd719b34f8db371bed9470ed40d ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 29721cd719b34f8db371bed9470ed40d';\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 2014 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_29721cd719b34f8db371bed9470ed40d()\"><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; R2013b<br><\/p><p class=\"footer\"><br>\r\n      Published with MATLAB&reg; R2013b<br><\/p><\/div><!--\r\n29721cd719b34f8db371bed9470ed40d ##### SOURCE BEGIN #####\r\n%% regionprops, tables, and struct2table\r\n% Today I was talking to Spandan (a regular guest blogger here) about the\r\n% history of the Image Processing Toolbox function |regionprops|. This\r\n% function is a widely-used work-horse of the toolbox. Many of my blog\r\n% posts here have shown it in practice.\r\n%\r\n% The function |regionprops| computes properties of regions of pixels. Most\r\n% often, these regions correspond to individual \"objects\" (connected\r\n% components of foreground pixels) of a binary image. Here's an example.\r\n\r\nbw = imread('text.png');\r\nimshow(bw)\r\n\r\n%%\r\n\r\ns = regionprops(bw)\r\n\r\n%%\r\n% The output is an 88x1 struct array, elements of which contain measurements for\r\n% objects in the binary image. (We didn't tell |regionprops| what\r\n% measurements to compute, so it computed Area, Centroid, and BoundingBox\r\n% by default.) Here are the measurements for the 10th object.\r\n\r\ns(10)\r\n\r\n%%\r\n% This form of output is convenient in some ways but inconvenient or\r\n% awkward in others. For example, it requires the obscure\r\n% \"comma-separated-list\" syntax to get all the area measurements into a\r\n% single vector to call a function such as |mean|, |min|, or |max|.\r\n\r\na = [s.Area];\r\nmean(a)\r\n\r\n%%\r\n\r\nmin(a)\r\n\r\n%%\r\n\r\nmax(a)\r\n\r\n%%\r\n% In the comma-separated list syntax for struct arrays, the expression\r\n% |[s.Area]| automatically expands into the expression |[s(1).Area,\r\n% s(2).Area, ..., s(end).Area]|. But relatively few people recognize or\r\n% understand this syntax.\r\n%\r\n% Another inconvenient aspect of the struct array aspect is that it's hard\r\n% to get a tabular view of all the data. As shown above, you can see the\r\n% data for the 10th object by displaying |s(10)|, but it's hard to see all\r\n% the data for multiple objects. For example:\r\n\r\ns(1:5)\r\n\r\n%%\r\n% If I were designing |regionprops| from scratch today, based on the most\r\n% recent version of MATLAB, I would have |regionprops| return a |table|.\r\n% Tables were introduced as a new fundamental MATLAB type in R2013b. Here's\r\n% a simple example to illustrate.\r\n\r\nage = [38 43 38 40 49]';\r\nheight = [71 69 64 67 64]';\r\nweight = [176 163 131 133 119]';\r\nblood_pressure = [124 93; 109 77; 125 83; 117 75; 122 80];\r\nt = table(age,height,weight,blood_pressure)\r\n\r\n%%\r\n% |t.height| is an ordinary 5-by-1 vector of heights.\r\n\r\nt.height\r\n\r\n%%\r\n% |t.blood_pressure| is an ordinary 5-by-2 matrix. (Table \"variables\" are\r\n% often column vectors, but they can have any size as long as the number of\r\n% rows is the same as the height of the table.)\r\n\r\nt.blood_pressure\r\n\r\n%%\r\n% We are excited about the introduction of tables in MATLAB, and we think\r\n% they will gradually be used in more and more situations where previously\r\n% people used struct arrays.\r\n%\r\n% Such as |regionprops|.\r\n%\r\n% So what to do? \r\n%\r\n% Well, the function |struct2table| comes in very handy here! As you might\r\n% have guessed from the name, it automatically converts a struct array\r\n% into a table.\r\n%\r\n% Try it:\r\n\r\nt = struct2table(s)\r\n\r\n%%\r\n% Immediately, you can see that the data is much more easily visible with a\r\n% table. You get scrolling and editing if you open |t| in the Variable\r\n% Editor.\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2014\/table-variable-editor-screen-shot.png>>\r\n%\r\n% You can plot directly with the data in a table variable:\r\n\r\nimshow(bw)\r\nhold on\r\nplot(t.Centroid(:,1),t.Centroid(:,2),'r*')\r\naxis([.5 100.5 .5 100.5])\r\nhold off\r\n\r\n%%\r\n% Logical indexing comes in handy for filtering objects based on various\r\n% criteria. For example, the following code removes objects with area less\r\n% than 10 from the table.\r\n\r\nt(t.Area < 10,:) = [];\r\n\r\n%%\r\n% And you can easily export tables to various formats. Here is our table\r\n% exported to a .CSV file and then read into Excel.\r\n\r\nwritetable(t,'regionprops.csv');\r\n\r\n%%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2014\/excel-screen-shot.png>>\r\n%\r\n% I encourage everyone who has used |regionprops| to play around with\r\n% tables (assuming you have MATLAB R2013b) to see how they might be useful\r\n% in your own work.\r\n##### SOURCE END ##### 29721cd719b34f8db371bed9470ed40d\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2014\/excel-screen-shot.png\" onError=\"this.style.display ='none';\" \/><\/div><p>Today I was talking to Spandan (a regular guest blogger here) about the history of the Image Processing Toolbox function regionprops. This function is a widely-used work-horse of the toolbox. Many of... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2014\/02\/04\/regionprops-tables-and-struct2table\/\">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,90,76,36,122,308,68,168,1071,1069,1073],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/974"}],"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=974"}],"version-history":[{"count":7,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/974\/revisions"}],"predecessor-version":[{"id":3823,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/974\/revisions\/3823"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=974"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=974"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=974"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}