{"id":194,"date":"2008-01-31T10:15:44","date_gmt":"2008-01-31T15:15:44","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2008\/01\/31\/counting-occurrences-of-image-colors\/"},"modified":"2019-10-24T13:54:31","modified_gmt":"2019-10-24T17:54:31","slug":"counting-occurrences-of-image-colors","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2008\/01\/31\/counting-occurrences-of-image-colors\/","title":{"rendered":"Counting occurrences of image colors"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>Blog reader Andr&eacute; recently asked me how to count the number of times each color appears in an image.  One short solution involves\r\n      optional output arguments from the function <tt>unique<\/tt>, as well as the relatively new function <tt>accumarray<\/tt>.\r\n   <\/p>\r\n   <p>Let's look first at the function <tt>unique<\/tt>.  Probably most people use it with a single output argument, like this:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">v = [1 1 3 5 5 2 3 2 2]<\/pre><pre style=\"font-style:oblique\">\r\nv =\r\n\r\n     1     1     3     5     5     2     3     2     2\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">u = unique(v)<\/pre><pre style=\"font-style:oblique\">\r\nu =\r\n\r\n     1     2     3     5\r\n\r\n<\/pre><p><tt>unique<\/tt> can also return two additional outputs:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[u, m, n] = unique(v);\r\nm<\/pre><pre style=\"font-style:oblique\">\r\nm =\r\n\r\n     2     9     7     5\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">n<\/pre><pre style=\"font-style:oblique\">\r\nn =\r\n\r\n     1     1     3     4     4     2     3     2     2\r\n\r\n<\/pre><p>So what do <tt>m<\/tt> and <tt>n<\/tt> mean?  Well, <tt>m<\/tt> tells you where you can find the unique values in the original vector.  Specifically, <tt>m(1)<\/tt> is the index of the last occurrence of the value <tt>u(1)<\/tt> in the original vector <tt>v<\/tt>.  Similarly, <tt>m(3)<\/tt> is the index of the last occurrent of the value <tt>u(3)<\/tt> in <tt>v<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">fprintf(<span style=\"color: #A020F0\">'m(3) = %d; u(3) = %d, v(m(3)) = %d\\n'<\/span>, m(3), u(3), <span style=\"color: #0000FF\">...<\/span>\r\n    v(m(3)))<\/pre><pre style=\"font-style:oblique\">m(3) = 7; u(3) = 3, v(m(3)) = 3\r\n<\/pre><p>The output argument <tt>n<\/tt> gives you indices you can use to reconstruct the original vector from the vector of unique values.  In orders, <tt>v<\/tt> equals <tt>u(n)<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">u(n)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     1     1     3     5     5     2     3     2     2\r\n\r\n<\/pre><p>If you count how many times the value 2 appears in the vector <tt>n<\/tt>, that will tell you how many times the value <tt>u(2)<\/tt> appears in the vector <tt>v<\/tt>.  That brings us to the second function I mentioned, <tt>accumarray<\/tt>.  Here's the pertinent sentence from the function description in the doc:\r\n   <\/p>\r\n   <p><tt>A = accumarray(subs, val)<\/tt> creates an array <tt>A<\/tt> by accumulating elements of the vector <tt>val<\/tt> using the subscript in subs.\r\n   <\/p>\r\n   <p>Passing <tt>n<\/tt> as <tt>subs<\/tt> and 1 as <tt>val<\/tt> to <tt>accumarray<\/tt> gives us a way to count how many times each value of <tt>n<\/tt> appears.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">counts = accumarray(n(:), 1)<\/pre><pre style=\"font-style:oblique\">\r\ncounts =\r\n\r\n     2\r\n     3\r\n     2\r\n     2\r\n\r\n<\/pre><p><tt>counts(1)<\/tt> is the number of times that the value <tt>u(1)<\/tt> appears in <tt>v<\/tt>.  <tt>counts(2)<\/tt> is the number of times that the value <tt>u(2)<\/tt> appears in <tt>v<\/tt>, and so on.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #0000FF\">for<\/span> k = 1:numel(counts)\r\n    fprintf(<span style=\"color: #A020F0\">'The value %d appears %d times in v.\\n'<\/span>, <span style=\"color: #0000FF\">...<\/span>\r\n        u(k), counts(k));\r\n<span style=\"color: #0000FF\">end<\/span><\/pre><pre style=\"font-style:oblique\">The value 1 appears 2 times in v.\r\nThe value 2 appears 3 times in v.\r\nThe value 3 appears 2 times in v.\r\nThe value 5 appears 2 times in v.\r\n<\/pre><p>So <tt>unique<\/tt> and <tt>accumarray<\/tt> help to count the number of occurrences of scalars.  How do we adapt this technique to count colors?  Specifically, how do\r\n      we count how many times each unique color occurs in a M-by-N-by-3 truecolor image?\r\n   <\/p>\r\n   <p>First, we reshape the image so that the columns correspond to three color channels.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">rgb = imread(<span style=\"color: #A020F0\">'peppers.png'<\/span>);\r\nimshow(rgb)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/194\/count_color_occurrences_01.jpg\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">size(rgb)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n   384   512     3\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">rgb_columns = reshape(rgb, [], 3);\r\nsize(rgb_columns)<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n      196608           3\r\n\r\n<\/pre><p>Then we use our procedure above with <tt>unique<\/tt> and <tt>accumarray<\/tt>, except that the we add the <tt>'rows'<\/tt> option to <tt>unique<\/tt>.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[unique_colors, m, n] = unique(rgb_columns, <span style=\"color: #A020F0\">'rows'<\/span>);\r\ncolor_counts = accumarray(n, 1);\r\n\r\nfprintf(<span style=\"color: #A020F0\">'There are %d unique colors in the image.\\n'<\/span>, <span style=\"color: #0000FF\">...<\/span>\r\n    size(unique_colors, 1))<\/pre><pre style=\"font-style:oblique\">There are 99059 unique colors in the image.\r\n<\/pre><p>Finally, let's find out what color occurs most frequently.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">[max_count, idx] = max(color_counts);\r\n\r\nfprintf(<span style=\"color: #A020F0\">'The color [%d %d %d] occurs %d times.\\n'<\/span>, <span style=\"color: #0000FF\">...<\/span>\r\n    unique_colors(idx, 1), unique_colors(idx, 2), <span style=\"color: #0000FF\">...<\/span>\r\n    unique_colors(idx, 3), max_count)<\/pre><pre style=\"font-style:oblique\">The color [254 254 254] occurs 344 times.\r\n<\/pre><p>And where does this common color occur?<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = n == idx;\r\nbw = reshape(bw, size(rgb, 1), size(rgb, 2));\r\nimshow(bw)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/194\/count_color_occurrences_02.jpg\"> <script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_3002937189164eac90392ca197615926() {\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='3002937189164eac90392ca197615926 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 3002937189164eac90392ca197615926';\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 2008 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_3002937189164eac90392ca197615926()\"><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.5<br><\/p>\r\n<\/div>\r\n<!--\r\n3002937189164eac90392ca197615926 ##### SOURCE BEGIN #####\r\n%%\r\n% Blog reader Andr\u00c3\u00a9 recently asked me how to count the number of\r\n% times each color appears in an image.  One short solution\r\n% involves optional output arguments from the function |unique|,\r\n% as well as the relatively new function |accumarray|.\r\n%\r\n% Let's look first at the function |unique|.  Probably most\r\n% people use it with a single output argument, like this:\r\n\r\nv = [1 1 3 5 5 2 3 2 2]\r\n\r\n%%\r\nu = unique(v)\r\n\r\n%%\r\n% |unique| can also return two additional outputs:\r\n\r\n[u, m, n] = unique(v);\r\nm\r\n\r\n%%\r\nn\r\n\r\n%%\r\n% So what do |m| and |n| mean?  Well, |m| tells you where you can\r\n% find the unique values in the original vector.  Specifically,\r\n% |m(1)| is the index of the last occurrence of the value |u(1)| \r\n% in the original vector |v|.  Similarly, |m(3)| is the index of\r\n% the last occurrent of the value |u(3)| in |v|.\r\n\r\nfprintf('m(3) = %d; u(3) = %d, v(m(3)) = %d\\n', m(3), u(3), ...\r\n    v(m(3)))\r\n\r\n%%\r\n% The output argument |n| gives you indices you can use to\r\n% reconstruct the original vector from the vector of unique\r\n% values.  In orders, |v| equals |u(n)|.\r\n\r\nu(n)\r\n\r\n%%\r\n% If you count how many times the value 2 appears in the vector\r\n% |n|, that will tell you how many times the value |u(2)| appears\r\n% in the vector |v|.  That brings us to the second function I\r\n% mentioned, |accumarray|.  Here's the pertinent sentence from\r\n% the function description in the doc:\r\n%\r\n% |A = accumarray(subs, val)| creates an array |A| by accumulating \r\n% elements of the vector |val| using the subscript in subs.\r\n%\r\n% Passing |n| as |subs| and 1 as |val| to |accumarray| gives us a\r\n% way to count how many times each value of |n| appears.\r\n\r\ncounts = accumarray(n(:), 1)\r\n\r\n%%\r\n% |counts(1)| is the number of times that the value |u(1)|\r\n% appears in |v|.  |counts(2)| is the number of times that the\r\n% value |u(2)| appears in |v|, and so on.\r\n\r\nfor k = 1:numel(counts)\r\n    fprintf('The value %d appears %d times in v.\\n', ...\r\n        u(k), counts(k));\r\nend\r\n\r\n%%\r\n% So |unique| and |accumarray| help to count the number of\r\n% occurrences of scalars.  How do we adapt this technique to\r\n% count colors?  Specifically, how do we count how many times each\r\n% unique color occurs in a M-by-N-by-3 truecolor image?\r\n%\r\n% First, we reshape the image so that the columns correspond to\r\n% three color channels.\r\n\r\nrgb = imread('peppers.png');\r\nimshow(rgb)\r\n\r\n%%\r\nsize(rgb)\r\n\r\n%%\r\nrgb_columns = reshape(rgb, [], 3);\r\nsize(rgb_columns)\r\n\r\n%%\r\n% Then we use our procedure above with |unique| and |accumarray|,\r\n% except that the we add the |'rows'| option to |unique|.\r\n\r\n[unique_colors, m, n] = unique(rgb_columns, 'rows'); \r\ncolor_counts = accumarray(n, 1);\r\n\r\nfprintf('There are %d unique colors in the image.\\n', ...\r\n    size(unique_colors, 1))\r\n\r\n%%\r\n% Finally, let's find out what color occurs most frequently.\r\n\r\n[max_count, idx] = max(color_counts);\r\n\r\nfprintf('The color [%d %d %d] occurs %d times.\\n', ...\r\n    unique_colors(idx, 1), unique_colors(idx, 2), ...\r\n    unique_colors(idx, 3), max_count)\r\n\r\n%%\r\n% And where does this common color occur?\r\n\r\nbw = n == idx;\r\nbw = reshape(bw, size(rgb, 1), size(rgb, 2));\r\nimshow(bw)\r\n##### SOURCE END ##### 3002937189164eac90392ca197615926\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   Blog reader Andr&eacute; recently asked me how to count the number of times each color appears in an image.  One short solution involves\r\n      optional output arguments from the function... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2008\/01\/31\/counting-occurrences-of-image-colors\/\">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":[336,466,76,36,122,162,170,190,350],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/194"}],"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=194"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/194\/revisions"}],"predecessor-version":[{"id":3586,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/194\/revisions\/3586"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=194"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=194"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=194"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}