{"id":166,"date":"2007-08-21T09:39:36","date_gmt":"2007-08-21T13:39:36","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2007\/08\/21\/gray-scale-pixel-values-in-labeled-regions\/"},"modified":"2019-10-23T13:47:58","modified_gmt":"2019-10-23T17:47:58","slug":"gray-scale-pixel-values-in-labeled-regions","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2007\/08\/21\/gray-scale-pixel-values-in-labeled-regions\/","title":{"rendered":"Gray scale pixel values in labeled regions"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <p>The functions <tt>bwlabel<\/tt> and <tt>regionprops<\/tt> are very useful for measuring the properties of shapes in a binary image.  There are documentation examples and product demos\r\n      showing how to do this, and I've shown these functions in action several times in this blog.\r\n   <\/p>\r\n   <p>But sometimes I get questions about how to process pixel values in the \"original\" gray scale image.  In other words, suppose\r\n      your process is something like this:\r\n   <\/p>\r\n   <div>\r\n      <ul>\r\n         <li>Segment gray scale image to get a binary image of objects<\/li>\r\n         <li>Label the binary image objects using <tt>bwlabel<\/tt><\/li>\r\n         <li>Do something with the original gray scale pixel values corresponding to each labeled object<\/li>\r\n      <\/ul>\r\n   <\/div>\r\n   <p>This post is about how to do that last step.  Let's start by creating some simple sample images to work with.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">I = imread(<span style=\"color: #A020F0\">'coins.png'<\/span>);\r\nimshow(I)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/166\/labeled_regions_grayscale_01.jpg\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">bw = im2bw(I, graythresh(I));\r\nbw = imfill(bw, <span style=\"color: #A020F0\">'holes'<\/span>);\r\nimshow(bw)\r\ntitle(<span style=\"color: #A020F0\">'Thresholded, with holes filled'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/166\/labeled_regions_grayscale_02.jpg\"> <pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">L = bwlabel(bw);\r\nimshow(label2rgb(L, @jet, [.7 .7 .7]))\r\ntitle(<span style=\"color: #A020F0\">'Label matrix'<\/span>)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/166\/labeled_regions_grayscale_03.jpg\"> <p>The key for using <tt>L<\/tt> to process the pixels in <tt>I<\/tt> is to use <tt>regionprops<\/tt> to get the <tt>'PixelIdxList'<\/tt> for each labeled region.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s = regionprops(L, <span style=\"color: #A020F0\">'PixelIdxList'<\/span>)<\/pre><pre style=\"font-style:oblique\">\r\ns = \r\n\r\n10x1 struct array with fields:\r\n    PixelIdxList\r\n\r\n<\/pre><p><tt>s<\/tt> is a struct array.  <tt>s(k).PixelIdxList<\/tt> is a vector of the linear indices of the k-th region.  You can use these values to index directly into <tt>I<\/tt>.  For example, here is the mean pixel value of the 3rd coin:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">idx = s(3).PixelIdxList;\r\nmean(I(idx))<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n  172.8769\r\n\r\n<\/pre><p>You can also replace object pixel values in <tt>I<\/tt> by indexing on the left side of an assignment statement, like this:\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\"><span style=\"color: #228B22\">% Turn the 4th coin white and the 5th coin black:<\/span>\r\nJ = I;\r\nJ(s(4).PixelIdxList) = 255;\r\nJ(s(5).PixelIdxList) = 0;\r\nimshow(J)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/166\/labeled_regions_grayscale_04.jpg\"> <p>Here's a loop that replaces the pixel values for each coin by the mean pixel value for that coin:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">F = I;\r\n<span style=\"color: #0000FF\">for<\/span> k = 1:numel(s)\r\n    idx = s(k).PixelIdxList;\r\n    F(idx) = mean(I(idx));\r\n<span style=\"color: #0000FF\">end<\/span>\r\nimshow(F)<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/166\/labeled_regions_grayscale_05.jpg\"> <p>I'll finish with a question that <a href=\"https:\/\/blogs.mathworks.com\/steve\/2006\/04\/05\/all-about-pixel-colors-grayscale-and-binary-images\/#comment-6946\">Mat asked in a blog comment<\/a>: \"How can I find the location of the maximum pixel value in each labeled region?\"  Here's how to find the locations and then\r\n      plot them on top of the original image.  (In addition to <tt>'PixelIdxList'<\/tt>, I'll also ask <tt>regionprops<\/tt> for <tt>'PixelList'<\/tt>, which gives the x and y coordinates of each pixel in the region.)\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">s = regionprops(L, <span style=\"color: #A020F0\">'PixelIdxList'<\/span>, <span style=\"color: #A020F0\">'PixelList'<\/span>);\r\nimshow(I)\r\nhold <span style=\"color: #A020F0\">on<\/span>\r\n<span style=\"color: #0000FF\">for<\/span> k = 1:numel(s)\r\n    idx = s(k).PixelIdxList;\r\n    pixels_in_region_k = I(idx);\r\n    [max_value, max_idx] = max(pixels_in_region_k);\r\n    max_location = s(k).PixelList(max_idx, :);\r\n    plot(max_location(1), max_location(2), <span style=\"color: #A020F0\">'*'<\/span>)\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\/166\/labeled_regions_grayscale_06.jpg\"> <script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_55fe4cdb64104063b14df1f45935020a() {\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='55fe4cdb64104063b14df1f45935020a ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' 55fe4cdb64104063b14df1f45935020a';\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 = '';\r\n        copyright = '';\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_55fe4cdb64104063b14df1f45935020a()\"><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.4<br><\/p>\r\n<\/div>\r\n<!--\r\n55fe4cdb64104063b14df1f45935020a ##### SOURCE BEGIN #####\r\n%% Gray scale pixel values in labeled regions\r\n% The functions |bwlabel| and |regionprops| are very useful for measuring\r\n% the properties of shapes in a binary image.  There are documentation\r\n% examples and product demos showing how to do this, and I've shown these\r\n% functions in action several times in this blog.\r\n%\r\n% But sometimes I get questions about how to process pixel values in the\r\n% \"original\" gray scale image.  In other words, suppose your process is\r\n% something like this:\r\n%\r\n% * Segment gray scale image to get a binary image of objects\r\n% * Label the binary image objects using |bwlabel|\r\n% * Do something with the original gray scale pixel values corresponding\r\n% to each labeled object\r\n%\r\n% This post is about how to do that last step.  Let's start by creating\r\n% some simple sample images to work with.\r\n\r\nI = imread('coins.png');\r\nimshow(I)\r\n\r\n%%\r\nbw = im2bw(I, graythresh(I));\r\nbw = imfill(bw, 'holes');\r\nimshow(bw)\r\ntitle('Thresholded, with holes filled')\r\n\r\n%%\r\nL = bwlabel(bw);\r\nimshow(label2rgb(L, @jet, [.7 .7 .7]))\r\ntitle('Label matrix')\r\n\r\n%%\r\n% The key for using |L| to process the pixels in |I| is to use\r\n% |regionprops| to get the |'PixelIdxList'| for each labeled region.\r\ns = regionprops(L, 'PixelIdxList')\r\n\r\n%%\r\n% |s| is a struct array.  |s(k).PixelIdxList| is a vector of the linear\r\n% indices of the k-th region.  You can use these values to index directly\r\n% into |I|.  For example, here is the mean pixel value of the 3rd coin:\r\nidx = s(3).PixelIdxList;\r\nmean(I(idx))\r\n\r\n%%\r\n% You can also replace object pixel values in |I| by indexing on the left \r\n% side of an assignment statement, like this:\r\n\r\n% Turn the 4th coin white and the 5th coin black:\r\nJ = I;\r\nJ(s(4).PixelIdxList) = 255;\r\nJ(s(5).PixelIdxList) = 0;\r\nimshow(J)\r\n\r\n%%\r\n% Here's a loop that replaces the pixel values for each coin by the mean\r\n% pixel value for that coin:\r\n\r\nF = I;\r\nfor k = 1:numel(s)\r\n    idx = s(k).PixelIdxList;\r\n    F(idx) = mean(I(idx));\r\nend\r\nimshow(F)\r\n\r\n%%\r\n% I'll finish with a question that\r\n% <https:\/\/blogs.mathworks.com\/steve\/2006\/04\/05\/all-about-pixel-colors-grayscale-and-binary-images\/#comment-6946 \r\n% Mat asked in a blog comment>: \"How\r\n% can I find the location of the maximum pixel value in each labeled\r\n% region?\"  Here's how to find the locations and then plot them on top of\r\n% the original image.  (In addition to |'PixelIdxList'|, I'll also ask\r\n% |regionprops| for |'PixelList'|, which gives the x and y coordinates of\r\n% each pixel in the region.)\r\n\r\ns = regionprops(L, 'PixelIdxList', 'PixelList');\r\nimshow(I)\r\nhold on\r\nfor k = 1:numel(s)\r\n    idx = s(k).PixelIdxList;\r\n    pixels_in_region_k = I(idx);\r\n    [max_value, max_idx] = max(pixels_in_region_k);\r\n    max_location = s(k).PixelList(max_idx, :);\r\n    plot(max_location(1), max_location(2), '*')\r\nend\r\nhold off\r\n\r\n##### SOURCE END ##### 55fe4cdb64104063b14df1f45935020a\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   The functions bwlabel and regionprops are very useful for measuring the properties of shapes in a binary image.  There are documentation examples and product demos\r\n      showing how to do this,... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/08\/21\/gray-scale-pixel-values-in-labeled-regions\/\">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,82,90,84,136,76,36,152,122,308,162,68,168,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/166"}],"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=166"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/166\/revisions"}],"predecessor-version":[{"id":3556,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/166\/revisions\/3556"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}