{"id":2685,"date":"2017-09-11T16:26:42","date_gmt":"2017-09-11T20:26:42","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=2685"},"modified":"2019-11-01T17:15:03","modified_gmt":"2019-11-01T21:15:03","slug":"gray-scale-pixel-values-in-image-regions","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2017\/09\/11\/gray-scale-pixel-values-in-image-regions\/","title":{"rendered":"Gray-scale pixel values in image regions"},"content":{"rendered":"<div class=\"content\"><p><i>Before I dive into today's topic, I want to invite you to come back to the <a href=\"https:\/\/blogs.mathworks.com\/\">MATLAB Central Blogs page<\/a> in a couple of weeks. Look for something new to appear related to deep learning<\/i>.<\/p><p>Earlier today, I was looking at <a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/?term=tag%3A%22image+processing%22\">recent image processing questions<\/a> on MATLAB Answers, and I came across this question:<\/p><p><a href=\"https:\/\/www.mathworks.com\/matlabcentral\/answers\/355998-using-regionprops-to-change-intensity-of-blobs\">\"Using regionprops to change intensity of blobs\"<\/a><\/p><p>I thought to myself, \"I bet I've written about something like before.\" It turns out that I have -- but it was more than ten years ago! It is ever-so-slightly possible that a couple of you have not been reading this blog that long, so I thought I would update the post for you today.<\/p><p>The function <tt>regionprops<\/tt> is very useful for measuring the properties of shapes in a binary image.  There are documentation examples and product demos showing how to do this, and I've shown this function in action several times in this blog.<\/p><p>But sometimes I get questions about how to process pixel values in the \"original\" gray scale image.  In other words, suppose your process is something like this:<\/p><div><ul><li>Segment gray scale image to get a binary image of objects<\/li><li>Do something with the original gray scale pixel values corresponding to each blob in the binary image<\/li><\/ul><\/div><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 class=\"codeinput\">I = imread(<span class=\"string\">'coins.png'<\/span>);\r\nimshow(I)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/regionprops_gray_01.png\" alt=\"\"> <pre class=\"codeinput\">bw = imbinarize(I);\r\nbw = imfill(bw, <span class=\"string\">'holes'<\/span>);\r\nimshow(bw)\r\ntitle(<span class=\"string\">'Thresholded, with holes filled'<\/span>)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/regionprops_gray_02.png\" alt=\"\"> <p>The key to processing the pixels in <tt>I<\/tt> using the blobs in <tt>bw<\/tt> is to use <tt>regionprops<\/tt> to get the <tt>'PixelIdxList'<\/tt> for each blob.<\/p><pre class=\"codeinput\">s = regionprops(L, <span class=\"string\">'PixelIdxList'<\/span>)\r\n<\/pre><pre class=\"codeoutput\">\r\ns = \r\n\r\n  10&times;1 struct array with fields:\r\n\r\n    PixelIdxList\r\n\r\n<\/pre><pre class=\"codeinput\">s(1)\r\n<\/pre><pre class=\"codeoutput\">\r\nans = \r\n\r\n  struct with fields:\r\n\r\n    PixelIdxList: [2651&times;1 double]\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:<\/p><pre class=\"codeinput\">idx = s(3).PixelIdxList;\r\nmean(I(idx))\r\n<\/pre><pre class=\"codeoutput\">\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:<\/p><pre class=\"codeinput\"><span class=\"comment\">% 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)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/regionprops_gray_03.png\" alt=\"\"> <p>Here's a loop that replaces the pixel values for each coin by the mean pixel value for that coin:<\/p><pre class=\"codeinput\">F = I;\r\n<span class=\"keyword\">for<\/span> k = 1:numel(s)\r\n    idx = s(k).PixelIdxList;\r\n    F(idx) = mean(I(idx));\r\n<span class=\"keyword\">end<\/span>\r\nimshow(F)\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/steve\/files\/regionprops_gray_04.png\" alt=\"\"> <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 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.)<\/p><pre class=\"codeinput\">s = regionprops(L, <span class=\"string\">'PixelIdxList'<\/span>, <span class=\"string\">'PixelList'<\/span>);\r\nimshow(I)\r\nhold <span class=\"string\">on<\/span>\r\n<span class=\"keyword\">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 class=\"string\">'o'<\/span>,<span class=\"string\">'MarkerSize'<\/span>,10,<span class=\"keyword\">...<\/span>\r\n        <span class=\"string\">'MarkerFaceColor'<\/span>,<span class=\"string\">'w'<\/span>,<span class=\"string\">'MarkerEdgeColor'<\/span>,<span class=\"string\">'k'<\/span>)\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\/regionprops_gray_05.png\" alt=\"\"> <script language=\"JavaScript\"> <!-- \r\n    function grabCode_d38778b412f54dbfbb4179ce30503ccd() {\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='d38778b412f54dbfbb4179ce30503ccd ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' d38778b412f54dbfbb4179ce30503ccd';\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 2017 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_d38778b412f54dbfbb4179ce30503ccd()\"><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; R2017a<br><\/p><\/div><!--\r\nd38778b412f54dbfbb4179ce30503ccd ##### SOURCE BEGIN #####\r\n%% Gray scale pixel values in labeled regions\r\n%\r\n% _Before I dive into today's topic, I want to invite you to come back to\r\n% the <https:\/\/blogs.mathworks.com\/ MATLAB Central Blogs page> in a couple\r\n% of weeks. Look for something new to appear related to deep learning_.\r\n%\r\n% Earlier today, I was looking at <https:\/\/www.mathworks.com\/matlabcentral\/answers\/?term=tag%3A%22image+processing%22 \r\n% recent image processing questions> on\r\n% MATLAB Answers, and I came across this question:\r\n%\r\n% <https:\/\/www.mathworks.com\/matlabcentral\/answers\/355998-using-regionprops-to-change-intensity-of-blobs \r\n% \"Using regionprops to change intensity of blobs\">\r\n%\r\n% I thought to myself, \"I bet I've written about something like before.\" It\r\n% turns out that I have REPLACE_WITH_DASH_DASH but it was more than ten years ago! It is\r\n% ever-so-slightly possible that a couple of you have not been reading this\r\n% blog that long, so I thought I would update the post for you today.\r\n%\r\n% The function |regionprops| is 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 this\r\n% function 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% * Do something with the original gray scale pixel values corresponding\r\n% to each blob in the binary image\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 = imbinarize(I);\r\nbw = imfill(bw, 'holes');\r\nimshow(bw)\r\ntitle('Thresholded, with holes filled')\r\n\r\n%%\r\n% The key to processing the pixels in |I| using the blobs in |bw| is to use\r\n% |regionprops| to get the |'PixelIdxList'| for each blob.\r\ns = regionprops(L, 'PixelIdxList')\r\n\r\n%%\r\ns(1)\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),'o','MarkerSize',10,...\r\n        'MarkerFaceColor','w','MarkerEdgeColor','k')\r\nend\r\nhold off\r\n\r\n##### SOURCE END ##### d38778b412f54dbfbb4179ce30503ccd\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img src=\"https:\/\/blogs.mathworks.com\/steve\/files\/regionprops_gray_04.png\" class=\"img-responsive attachment-post-thumbnail size-post-thumbnail wp-post-image\" alt=\"\" decoding=\"async\" loading=\"lazy\" \/><\/div><p>Before I dive into today's topic, I want to invite you to come back to the MATLAB Central Blogs page in a couple of weeks. Look for something new to appear related to deep learning.Earlier today, I... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2017\/09\/11\/gray-scale-pixel-values-in-image-regions\/\">read more >><\/a><\/p>","protected":false},"author":42,"featured_media":2690,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":[],"categories":[1],"tags":[90,1155,136,76,36,122,308,162,68,168,52],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/2685"}],"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=2685"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/2685\/revisions"}],"predecessor-version":[{"id":2686,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/2685\/revisions\/2686"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media\/2690"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=2685"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=2685"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=2685"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}