{"id":154,"date":"2007-07-20T14:34:08","date_gmt":"2007-07-20T18:34:08","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/2007\/07\/20\/imoverlay-and-imagesc\/"},"modified":"2019-10-23T13:42:53","modified_gmt":"2019-10-23T17:42:53","slug":"imoverlay-and-imagesc","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2007\/07\/20\/imoverlay-and-imagesc\/","title":{"rendered":"imoverlay and imagesc"},"content":{"rendered":"<div xmlns:mwsh=\"https:\/\/www.mathworks.com\/namespace\/mcode\/v1\/syntaxhighlight.dtd\" class=\"content\">\r\n   <introduction>\r\n      <p>In <a href=\"https:\/\/blogs.mathworks.com\/steve\/2006\/03\/28\/image-overlays\/\">March 2006<\/a> I wrote about how to overlay a specified color onto specified pixels of a grayscale or RGB image. I put a utility function\r\n         (<a title=\"https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/loadFile.do?objectId=10502&amp;objectType=file (link no longer works)\"><tt>imoverlay<\/tt><\/a>) for performing this operation on the MATLAB Central File Exchange.\r\n      <\/p>\r\n      <p>Earlier this week, Matt W. posted a review of that submission, suggesting that additional documentation might be helpful for\r\n         people displaying image data that's not in the range [0, 1].  MATLAB users often call <tt>imagesc<\/tt> to \"autoscale\" image data, and Image Processing Toolbox users can call <tt>imshow(I,[])<\/tt> to get a similar effect.\r\n      <\/p>\r\n      <p>Here's an example using <tt>imagesc<\/tt>.\r\n      <\/p>\r\n   <\/introduction><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">L = membrane(1, 100);\r\nimagesc(L), axis <span style=\"color: #A020F0\">equal<\/span>, colormap(hot)\r\naxis <span style=\"color: #A020F0\">equal<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/154\/imoverlay_gray2ind_01.jpg\"> <p>Note that L has negative values.<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">min(L(:))<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n   -0.3338\r\n\r\n<\/pre><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">max(L(:))<\/pre><pre style=\"font-style:oblique\">\r\nans =\r\n\r\n     1\r\n\r\n<\/pre><p><tt>imagesc<\/tt> automatically scales the values of <tt>L<\/tt> \"into\" the colormap, so that the minimum value is displaying using the first colormap color and the maximum value is displayed\r\n      using the last colormap color.  (See my post about <a href=\"https:\/\/blogs.mathworks.com\/steve\/2006\/02\/10\/all-about-pixel-colors-part-3\/\">scaled indexed images<\/a>.)\r\n   <\/p>\r\n   <p>Although Matt's specific suggestion was about getting <tt>imoverlay<\/tt> to work with this data, there's a more general concept here about how to save images like the one above to image file formats,\r\n      such as JPEG or PNG.  Image file formats have generally much less flexibility than MATLAB about displaying pixel values as\r\n      colors.  In particular, the most common formats don't have the notion of scaling an arbitrary range of data values into a\r\n      colormap.  In addition, the JPEG format doesn't even have the notion of using a colormap at all.\r\n   <\/p>\r\n   <p>We could try writing the L values directly into a JPEG file, like this:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">imwrite(L,<span style=\"color: #A020F0\">'membrane1.jpg'<\/span>)\r\nimshow <span style=\"color: #A020F0\">membrane1.jpg<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/154\/imoverlay_gray2ind_02.jpg\"> <p>But we lost all the color information, and there's no automatic data scaling.  All the values of <tt>L<\/tt> less than 0 were simply clipped to black in the JPEG file.\r\n   <\/p>\r\n   <p>So how can we turn <tt>L<\/tt> and the hot colormap into something that can be stored in a JPEG file?\r\n   <\/p>\r\n   <p>We can do it in three steps:<\/p>\r\n   <div>\r\n      <ul>\r\n         <li>Scale <tt>L<\/tt> into the dynamic range [0, 1] by using <tt>mat2gray<\/tt>.\r\n         <\/li>\r\n         <li>Convert the result into a normal (unscaled) indexed image using <tt>gray2ind<\/tt>.\r\n         <\/li>\r\n         <li>Convert the indexed image into RGB form by using <tt>ind2rgb<\/tt>.\r\n         <\/li>\r\n      <\/ul>\r\n   <\/div><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">gray = mat2gray(L);\r\nX = gray2ind(gray, 256);\r\nrgb = ind2rgb(X, hot(256));\r\n\r\nimwrite(rgb, <span style=\"color: #A020F0\">'membrane2.jpg'<\/span>)\r\nimshow <span style=\"color: #A020F0\">membrane2.jpg<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/154\/imoverlay_gray2ind_03.jpg\"> <p>Now that the membrane image is in RGB form, we can use <tt>imoverlay<\/tt>.  For example, let's overlay all the negative pixels with a light blue color.\r\n   <\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">mask = L &lt; 0;\r\nlight_blue = [.6 .6 1];\r\noverlay = imoverlay(rgb, mask, light_blue);\r\n\r\nimwrite(overlay, <span style=\"color: #A020F0\">'membrane3.jpg'<\/span>)\r\nimshow <span style=\"color: #A020F0\">membrane3.jpg<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/154\/imoverlay_gray2ind_04.jpg\"> <p>Of course, every time you launch MATLAB you see this membrane shape in a more familiar form that looks something like this:<\/p><pre style=\"background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)\">membrane(1,50)\r\ncolormap(hot)\r\ncamlight\r\nshading <span style=\"color: #A020F0\">interp<\/span><\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/154\/imoverlay_gray2ind_05.jpg\"> <p>The L-shaped membrane has played a fascinating role in the history of MATLAB and The MathWorks.  If you are interested in\r\n      the origins and history of MATLAB, you should check out the <a href=\"https:\/\/www.mathworks.com\/company\/aboutus\/founders\/clevemoler.html\"><i>Origins of MATLAB<\/i> video<\/a> by MATLAB creator and company co-founder Cleve Moler.\r\n   <\/p><script language=\"JavaScript\">\r\n<!--\r\n\r\n    function grabCode_f48a9c06b9cf4a4498d4dea83649b7cd() {\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='f48a9c06b9cf4a4498d4dea83649b7cd ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' f48a9c06b9cf4a4498d4dea83649b7cd';\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 2007 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_f48a9c06b9cf4a4498d4dea83649b7cd()\"><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\nf48a9c06b9cf4a4498d4dea83649b7cd ##### SOURCE BEGIN #####\r\n%%\r\n% In <https:\/\/blogs.mathworks.com\/steve\/2006\/03\/28\/image-overlays\/ \r\n% March 2006> I wrote about how to overlay a specified color onto\r\n% specified pixels of a grayscale or RGB image. I put a utility\r\n% function (<https:\/\/www.mathworks.com\/matlabcentral\/fileexchange\/loadFile.do?objectId=10502&objectType=file \r\n% |imoverlay|>) for performing this operation on the\r\n% MATLAB Central File Exchange.\r\n%\r\n% Earlier this week, Matt W. posted a review of that submission, suggesting\r\n% that additional documentation might be helpful for people displaying\r\n% image data that's not in the range [0, 1].  MATLAB users often call \r\n% |imagesc| to \"autoscale\" image data, and Image Processing Toolbox users \r\n% can call |imshow(I,[])| to get a similar effect.\r\n%\r\n% Here's an example using |imagesc|.\r\n\r\n%%\r\nL = membrane(1, 100);\r\nimagesc(L), axis equal, colormap(hot)\r\naxis equal\r\n\r\n%%\r\n% Note that L has negative values.\r\n\r\nmin(L(:))\r\n\r\n%%\r\nmax(L(:))\r\n\r\n%%\r\n% |imagesc| automatically scales the values of |L| \"into\" the colormap, so\r\n% that the minimum value is displaying using the first colormap color and the\r\n% maximum value is displayed using the last colormap color.  (See my post\r\n% about\r\n% <https:\/\/blogs.mathworks.com\/steve\/2006\/02\/10\/all-about-pixel-colors-part-3\/ \r\n% scaled indexed images>.)\r\n\r\n%%\r\n% Although Matt's specific suggestion was about getting |imoverlay| to\r\n% work with this data, there's a more general concept here about how to\r\n% save images like the one above to image file formats, such as JPEG or\r\n% PNG.  Image file formats have generally much less flexibility than MATLAB\r\n% about displaying pixel values as colors.  In particular, the most common\r\n% formats don't have the notion of scaling an arbitrary range of data\r\n% values into a colormap.  In addition, the JPEG format doesn't even have\r\n% the notion of using a colormap at all.\r\n%\r\n% We could try writing the L values directly into a JPEG file, like this:\r\n\r\nimwrite(L,'membrane1.jpg')\r\nimshow membrane1.jpg\r\n\r\n%%\r\n% But we lost all the color information, and there's no automatic data\r\n% scaling.  All the values of |L| less than 0 were simply clipped to black in\r\n% the JPEG file.\r\n%\r\n% So how can we turn |L| and the hot colormap into something that can be\r\n% stored in a JPEG file?\r\n%\r\n% We can do it in three steps:\r\n%\r\n% * Scale |L| into the dynamic range [0, 1] by using |mat2gray|.\r\n% * Convert the result into a normal (unscaled) indexed image using\r\n% |gray2ind|.\r\n% * Convert the indexed image into RGB form by using |ind2rgb|.\r\n\r\ngray = mat2gray(L);\r\nX = gray2ind(gray, 256);\r\nrgb = ind2rgb(X, hot(256));\r\n\r\nimwrite(rgb, 'membrane2.jpg')\r\nimshow membrane2.jpg\r\n\r\n%%\r\n% Now that the membrane image is in RGB form, we can use |imoverlay|.  For\r\n% example, let's overlay all the negative pixels with a light blue color.\r\n\r\nmask = L < 0;\r\nlight_blue = [.6 .6 1];\r\noverlay = imoverlay(rgb, mask, light_blue);\r\n\r\nimwrite(overlay, 'membrane3.jpg')\r\nimshow membrane3.jpg\r\n\r\n%%\r\n% Of course, every time you launch MATLAB you see this membrane shape in a\r\n% more familiar form that looks something like this:\r\nmembrane(1,50)\r\ncolormap(hot)\r\ncamlight\r\nshading interp\r\n\r\n%%\r\n% The L-shaped membrane has played a fascinating role in the history of\r\n% MATLAB and The MathWorks.  If you are interested in the origins and\r\n% history of MATLAB, you should check out the <https:\/\/www.mathworks.com\/company\/aboutus\/founders\/clevemoler.html\r\n% _Origins of MATLAB_ video>\r\n% by MATLAB creator and company co-founder Cleve Moler.\r\n\r\n##### SOURCE END ##### f48a9c06b9cf4a4498d4dea83649b7cd\r\n-->","protected":false},"excerpt":{"rendered":"<p>\r\n   \r\n      In March 2006 I wrote about how to overlay a specified color onto specified pixels of a grayscale or RGB image. I put a utility function\r\n         (imoverlay) for performing this... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2007\/07\/20\/imoverlay-and-imagesc\/\">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,218,58,382,60,36,164,384,122,378,380,386],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/154"}],"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=154"}],"version-history":[{"count":1,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/154\/revisions"}],"predecessor-version":[{"id":3550,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/154\/revisions\/3550"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=154"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=154"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=154"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}