{"id":365,"date":"2011-03-22T22:34:12","date_gmt":"2011-03-23T02:34:12","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2011\/03\/22\/too-much-information-about-the-size-function\/"},"modified":"2019-10-29T16:32:31","modified_gmt":"2019-10-29T20:32:31","slug":"too-much-information-about-the-size-function","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2011\/03\/22\/too-much-information-about-the-size-function\/","title":{"rendered":"Too much information about the size function"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>Today's post is proof that this old MATLAB dog can learn new tricks. The subject is this: Given an image array, how can you\r\n      most easily determine the number of rows and columns it has? (In code, that is; I don't mean by looking at the Workspace Browser!)\r\n   <\/p>\r\n   <p>I'm going to take an indirect path to get there:<\/p>\r\n   <p>1. I'll explain a general principle of MATLAB function behavior.<\/p>\r\n   <p>2. I'll show the that the <tt>size<\/tt> function violates this principle.\r\n   <\/p>\r\n   <p>3. I'll show how a common use of <tt>size<\/tt> can lead you astray.\r\n   <\/p>\r\n   <p>4. I'll show the code I used to use.<\/p>\r\n   <p>5. Finally I'll show how to do it a new \"trick\" (that <a href=\"https:\/\/blogs.mathworks.com\/loren\">Loren<\/a> taught me) which uses a fairly recent addition to the MATLAB language.\r\n   <\/p>\r\n   <p>There's nothing profound here, but there are some subtle issues about using <tt>size<\/tt> with multidimensional arrays that image processing users should probably be aware of. (I'll warn you here --- if you're already\r\n      bored with this topic, the rest of the post doesn't get better. You should probably just go read one of the <a href=\"https:\/\/blogs.mathworks.com\/\">other MATLAB Central blogs<\/a> instead.)\r\n   <\/p>\r\n   <p>The general principle of MATLAB function behavior is about functions with multiple output arguments. For example, the Image\r\n      Processing Toolbox function <tt>bwlabel<\/tt> has two output arguments. A sample call using both output arguments is:\r\n   <\/p><pre>  [L,n] = bwlabel(BW);<\/pre><p>The first output argument is the label matrix, and the second argument is the number of labeled objects.<\/p>\r\n   <p>For most MATLAB functions, the meaning of each output argument does not depend on how many output arguments are specified\r\n      when the function is called. In the example above, if you call <tt>bwlabel<\/tt> with only one output argument, that output is still the label matrix.  The second output argument is silently dropped by\r\n      MATLAB. And if you call the function with no output argument, the first output is still the label matrix and is used to set\r\n      the automatic workspace variable <tt>ans<\/tt>.\r\n   <\/p>\r\n   <p>I can think of three kinds of exceptions to this behavior. In the first case, common to many graphics functions, a function\r\n      returns something (like a handle) if called with an output argument, but it returns nothing if called without an output argument.\r\n      Examples in this category include <tt>plot<\/tt> and <tt>bar<\/tt>.\r\n   <\/p>\r\n   <p>The second kind of exception is for functions that \"pretty-print\" something to the Command Window if called without an output\r\n      argument and return a value if called with an output argument. Examples include <tt>dir<\/tt> and <tt>whos<\/tt>.\r\n   <\/p>\r\n   <p>The third category is (unfortunately) the \"everything else\" exceptions. And <tt>size<\/tt> is in this group.\r\n   <\/p>\r\n   <p>You can see the exceptional behavior with your plain ol' two-dimensional matrices. Consider the following two calls to size:<\/p><pre> A = rand(3,4);  % A is 3-by-4\r\n m = size(A);\r\n [m,n] = size(A);<\/pre><p><tt>m<\/tt> is not the same in both cases. In the first case, <tt>size<\/tt> returns the size vector, <tt>[3 4]<\/tt>. In the second case, <tt>m<\/tt> is the number of rows (3) and <tt>n<\/tt> is the number of columns (4).\r\n   <\/p>\r\n   <p>For higher dimensional arrays it gets more interesting. The rule is this: If you call <tt>size<\/tt> with two or more output arguments, the last output argument is the number of elements in that array dimension <i>and all the remaining dimensions of the array<\/i>.\r\n   <\/p>\r\n   <p>It's probably easier to just show you. Let's look at a 3-by-4-by-5 array and calls to <tt>size<\/tt> with a different number of output arguments.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">B = rand(3,4,5);\r\n[m,n,p] = size(B)<\/pre><pre style=\"font-style:oblique\">\r\nm =\r\n\r\n     3\r\n\r\n\r\nn =\r\n\r\n     4\r\n\r\n\r\np =\r\n\r\n     5\r\n\r\n<\/pre><p>Not surprising. Now just call it with just two output arguments:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[m,n] = size(B)<\/pre><pre style=\"font-style:oblique\">\r\nm =\r\n\r\n     3\r\n\r\n\r\nn =\r\n\r\n    20\r\n\r\n<\/pre><p>Now the second output is 20 instead of 4! That's because 4*5 is 20.  For fun, call size with 4 outputs:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[m,n,p,q] = size(B)<\/pre><pre style=\"font-style:oblique\">\r\nm =\r\n\r\n     3\r\n\r\n\r\nn =\r\n\r\n     4\r\n\r\n\r\np =\r\n\r\n     5\r\n\r\n\r\nq =\r\n\r\n     1\r\n\r\n<\/pre><p>MATLAB is perfectly happy to treat <tt>B<\/tt> as a four-dimensional array whose last dimension has size 1. That's actually pretty useful, even essential, for writing reasonable-looking\r\n      multidimensional code in MATLAB.\r\n   <\/p>\r\n   <p>Now let me connect this back to the problem I posed at the very beginning: find the number of rows and columns in an image\r\n      array. Let's make it a concrete example:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">neb = imread(<span style=\"color: #A020F0\">'ngc6543a.jpg'<\/span>);\r\nimshow(neb, <span style=\"color: #A020F0\">'InitialMagnification'<\/span>, 50)\r\ntitle(<span style=\"color: #A020F0\">'Obligatory image'<\/span>)\r\nxlabel(<span style=\"color: #A020F0\">'This blog is supposed to be about image processing after all'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2011\/size_tricks_01.jpg\"> <p>Here's the naive attempt to ask for the number of rows and columns in our image:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[nrows,ncols] = size(neb)<\/pre><pre style=\"font-style:oblique\">\r\nnrows =\r\n\r\n   650\r\n\r\n\r\nncols =\r\n\r\n        1800\r\n\r\n<\/pre><p>But unfortunately that's not right because <tt>neb<\/tt> is a 3-D array. Therefore the second output is the number of columns times 3, the number of color planes. There are two ways\r\n      I've always used to make sure I get the right answer. The first is to call <tt>size<\/tt> with three output arguments, even though I only need two:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[nrows,ncols,junk] = size(neb)<\/pre><pre style=\"font-style:oblique\">\r\nnrows =\r\n\r\n   650\r\n\r\n\r\nncols =\r\n\r\n   600\r\n\r\n\r\njunk =\r\n\r\n     3\r\n\r\n<\/pre><p>I always found this vaguely unsatisfactory because I don't like unused variables cluttering up my code. The second way requires\r\n      two separate calls to <tt>size<\/tt>:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">nrows = size(neb,1)<\/pre><pre style=\"font-style:oblique\">\r\nnrows =\r\n\r\n   650\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">ncols = size(neb,2)<\/pre><pre style=\"font-style:oblique\">\r\nncols =\r\n\r\n   600\r\n\r\n<\/pre><p><a href=\"https:\/\/blogs.mathworks.com\/loren\">Loren<\/a> pointed out to me recently that a feature added to R2009b, using the tilde character in input and output argument lists,\r\n      can be used here. Used in an output argument list, the tilde character says to MATLAB, \"Hey, I'm not going to need this output\r\n      argument and don't want to even give it a variable name, so please just clean it up automatically for me.\" Loren and I both\r\n      posted about this feature (<a href=\"https:\/\/blogs.mathworks.com\/loren\/2009\/09\/11\/matlab-release-2009b-best-new-feature-or\/\">hers<\/a> and <a href=\"https:\/\/blogs.mathworks.com\/steve\/2010\/01\/11\/about-the-unused-argument-syntax-in-r2009b\/\">mine<\/a>) if you want to go read more about it. As I recall, not everyone was a fan. Oh, well. I like it.\r\n   <\/p>\r\n   <p>Anyway, here's how you can use it in the call to <tt>size<\/tt>:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[nrows,ncols,~] = size(neb)<\/pre><pre style=\"font-style:oblique\">\r\nnrows =\r\n\r\n   650\r\n\r\n\r\nncols =\r\n\r\n   600\r\n\r\n<\/pre><p>Maybe this was more than you really wanted to know about <tt>size<\/tt>. However, I think that if you regularly write code that handles multidimensional arrays, eventually you'll be happy that\r\n      you made it all the way to the end.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_ee5529058d064ca5a24ef7c4309e624b() {\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='ee5529058d064ca5a24ef7c4309e624b ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' ee5529058d064ca5a24ef7c4309e624b';\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_ee5529058d064ca5a24ef7c4309e624b()\"><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.11<br><\/p>\r\n<\/div>\r\n<!--\r\nee5529058d064ca5a24ef7c4309e624b ##### SOURCE BEGIN #####\r\n%%\r\n% Today's post is proof that this old MATLAB dog can learn new tricks. The\r\n% subject is this: Given an image array, how can you most easily determine\r\n% the number of rows and columns it has? (In code, that is; I don't mean by\r\n% looking at the Workspace Browser!)\r\n%\r\n% I'm going to take an indirect path to get there:\r\n%\r\n% 1. I'll explain a general principle of MATLAB function behavior.\r\n%\r\n% 2. I'll show the that the |size| function violates this principle.\r\n%\r\n% 3. I'll show how a common use of |size| can lead you astray.\r\n%\r\n% 4. I'll show the code I used to use.\r\n%\r\n% 5. Finally I'll show how to do it a new \"trick\" (that \r\n% <https:\/\/blogs.mathworks.com\/loren Loren> taught me)\r\n% which uses a fairly recent addition to the MATLAB language.\r\n%\r\n% There's nothing profound here, but there are some subtle issues about\r\n% using |size| with multidimensional arrays that image processing users\r\n% should probably be aware of. (I'll warn you here REPLACE_WITH_DASH_DASH- if you're already\r\n% bored with this topic, the rest of the post doesn't get better. You\r\n% should probably just go read one of the <https:\/\/blogs.mathworks.com\/\r\n% other MATLAB Central blogs> instead.)\r\n%\r\n% The general principle of MATLAB function behavior is about functions with\r\n% multiple output arguments. For example, the Image Processing Toolbox\r\n% function |bwlabel| has two output arguments. A sample call using both\r\n% output arguments is:\r\n%\r\n%    [L,n] = bwlabel(BW);\r\n%\r\n% The first output argument is the label matrix, and the second argument is\r\n% the number of labeled objects.\r\n%\r\n% For most MATLAB functions, the meaning of each output argument does not\r\n% depend on how many output arguments are specified when the function is\r\n% called. In the example above, if you call |bwlabel| with only one output\r\n% argument, that output is still the label matrix.  The second output\r\n% argument is silently dropped by MATLAB. And if you call the function with\r\n% no output argument, the first output is still the label matrix and is\r\n% used to set the automatic workspace variable |ans|.\r\n%\r\n% I can think of three kinds of exceptions to this behavior. In the first\r\n% case, common to many graphics functions, a function returns something\r\n% (like a handle) if called with an output argument, but it returns nothing\r\n% if called without an output argument. Examples in this category include\r\n% |plot| and |bar|.\r\n%\r\n% The second kind of exception is for functions that \"pretty-print\"\r\n% something to the Command Window if called without an output argument and\r\n% return a value if called with an output argument. Examples include |dir|\r\n% and |whos|.\r\n%\r\n% The third category is (unfortunately) the \"everything else\" exceptions.\r\n% And |size| is in this group.\r\n%\r\n% You can see the exceptional behavior with your plain ol' two-dimensional\r\n% matrices. Consider the following two calls to size:\r\n%\r\n%   A = rand(3,4);  % A is 3-by-4\r\n%   m = size(A);\r\n%   [m,n] = size(A);\r\n%\r\n% |m| is not the same in both cases. In the first case, |size| returns the\r\n% size vector, |[3 4]|. In the second case, |m| is the number of rows (3)\r\n% and |n| is the number of columns (4).\r\n%\r\n% For higher dimensional arrays it gets more interesting. The rule is this:\r\n% If you call |size| with two or more output arguments, the last output\r\n% argument is the number of elements in that array dimension _and all the\r\n% remaining dimensions of the array_.\r\n%\r\n% It's probably easier to just show you. Let's look at a 3-by-4-by-5 array\r\n% and calls to |size| with a different number of output arguments.\r\n\r\nB = rand(3,4,5);\r\n[m,n,p] = size(B)\r\n\r\n%%\r\n% Not surprising. Now just call it with just two output arguments:\r\n\r\n[m,n] = size(B)\r\n\r\n%%\r\n% Now the second output is 20 instead of 4! That's because 4*5 is 20.  For\r\n% fun, call size with 4 outputs:\r\n\r\n[m,n,p,q] = size(B)\r\n\r\n%%\r\n% MATLAB is perfectly happy to treat |B| as a four-dimensional array whose\r\n% last dimension has size 1. That's actually pretty useful, even essential,\r\n% for writing reasonable-looking multidimensional code in MATLAB.\r\n%\r\n% Now let me connect this back to the problem I posed at the very\r\n% beginning: find the number of rows and columns in an image array. Let's\r\n% make it a concrete example:\r\n\r\nneb = imread('ngc6543a.jpg');\r\nimshow(neb, 'InitialMagnification', 50)\r\ntitle('Obligatory image')\r\nxlabel('This blog is supposed to be about image processing after all')\r\n\r\n%%\r\n% Here's the naive attempt to ask for the number of rows and columns in our\r\n% image:\r\n\r\n[nrows,ncols] = size(neb)\r\n\r\n%%\r\n% But unfortunately that's not right because |neb| is a 3-D array.\r\n% Therefore the second output is the number of columns times 3, the number\r\n% of color planes. There are two ways I've always used to make sure I get\r\n% the right answer. The first is to call |size| with three output\r\n% arguments, even though I only need two:\r\n\r\n[nrows,ncols,junk] = size(neb)\r\n\r\n%%\r\n% I always found this vaguely unsatisfactory because I don't like unused\r\n% variables cluttering up my code. The second way requires two separate\r\n% calls to |size|:\r\n\r\nnrows = size(neb,1)\r\n\r\n%%\r\n\r\nncols = size(neb,2)\r\n\r\n%%\r\n% <https:\/\/blogs.mathworks.com\/loren Loren> pointed out to me recently that\r\n% a feature added to R2009b, using the tilde character in input and output\r\n% argument lists, can be used here. Used in an output argument list, the\r\n% tilde character says to MATLAB, \"Hey, I'm not going to need this output\r\n% argument and don't want to even give it a variable name, so please just\r\n% clean it up automatically for me.\" Loren and I both posted about this\r\n% feature\r\n% (<https:\/\/blogs.mathworks.com\/loren\/2009\/09\/11\/matlab-release-2009b-best-new-feature-or\/\r\n% hers> and\r\n% <https:\/\/blogs.mathworks.com\/steve\/2010\/01\/11\/about-the-unused-argument-syntax-in-r2009b\/\r\n% mine>) if you want to go read more about it. As I recall, not everyone\r\n% was a fan. Oh, well. I like it.\r\n%\r\n% Anyway, here's how you can use it in the call to |size|:\r\n\r\n[nrows,ncols,~] = size(neb)\r\n\r\n%%\r\n% Maybe this was more than you really wanted to know about |size|. However,\r\n% I think that if you regularly write code that handles multidimensional\r\n% arrays, eventually you'll be happy that you made it all the way to the\r\n% end.\r\n\r\n\r\n\r\n##### SOURCE END ##### ee5529058d064ca5a24ef7c4309e624b\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   Today's post is proof that this old MATLAB dog can learn new tricks. The subject is this: Given an image array, how can you\r\n      most easily determine the number of rows and columns it has?... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2011\/03\/22\/too-much-information-about-the-size-function\/\">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":[166,76,36,460,190,52,94],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/365"}],"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=365"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/365\/revisions"}],"predecessor-version":[{"id":3725,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/365\/revisions\/3725"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=365"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=365"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=365"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}