{"id":766,"date":"2013-02-21T17:15:45","date_gmt":"2013-02-21T22:15:45","guid":{"rendered":"https:\/\/blogs.mathworks.com\/steve\/?p=766"},"modified":"2019-11-01T09:11:18","modified_gmt":"2019-11-01T13:11:18","slug":"revisiting-dctdemo-part-2","status":"publish","type":"post","link":"https:\/\/blogs.mathworks.com\/steve\/2013\/02\/21\/revisiting-dctdemo-part-2\/","title":{"rendered":"Revisiting dctdemo &#8211; part 2"},"content":{"rendered":"\r\n<div class=\"content\"><p>This is the second part of my plan to rewrite an Image Processing Toolbox example from 20 years ago using more modern MATLAB language features.<\/p><p>Recall the old app I'm trying to reinvent:<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2013\/dctdemo-screen-shot.png\" alt=\"\"> <\/p><p>The idea is to experiment with the basic principles of DCT-based image compression. I've decided that I don't want to copy this original layout and functionality exactly. For one thing, computers (and MATLAB!) are a lot faster than they were 20 years ago, and I think we really don't need a separate \"Apply\" button.<\/p><p>Here's my first attempt at sketching what I'd like to make this time around.<\/p><p><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2013\/dct-compression-sketch.jpg\" alt=\"\"> <\/p><p>The truth, is, I'm making the code and these posts up as I go along. So far I've only had a chance to get some of the initial pieces up and working. But it's enough to start exploring some of the coding ideas.<\/p><p>Here's what happens when I call the app class, which I've called (for now) <tt>dctCompressionExample_v2<\/tt>.<\/p><pre class=\"codeinput\">app = dctCompressionExample_v2\r\n<\/pre><pre class=\"codeoutput\">\r\napp = \r\n\r\n  dctCompressionExample_v2 handle\r\n\r\n  Properties:\r\n         OriginalImage: [240x240 double]\r\n    ReconstructedImage: []\r\n            ErrorImage: []\r\n    DCTCoefficientMask: []\r\n    NumDCTCoefficients: 10\r\n\r\n\r\n<\/pre><img decoding=\"async\" vspace=\"5\" hspace=\"5\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2013\/dctdemo_part2_01.png\" alt=\"\"> <p>You can see I got some output in the Command Window, and I also got a new figure on the screen.<\/p><p>Here's the code so far.<\/p><pre>classdef dctCompressionExample_v2 &lt; handle<\/pre><pre>    properties (SetAccess = private)\r\n        OriginalImage\r\n        ReconstructedImage\r\n        ErrorImage\r\n        DCTCoefficientMask\r\n    end<\/pre><pre>    properties\r\n        NumDCTCoefficients = 10\r\n    end<\/pre><pre>    properties (Access = private)\r\n        Slider\r\n        OriginalImageAxes\r\n        ReconstructedImageAxes\r\n        ErrorImageAxes\r\n        MaskAxes\r\n    end<\/pre><pre>    methods\r\n        function this_app = dctCompressionExample_v2\r\n            this_app.OriginalImage = initialImage;\r\n            layoutApp(this_app);\r\n            update(this_app);\r\n        end<\/pre><pre>        function layoutApp(app)\r\n            f = figure;\r\n            app.OriginalImageAxes = axes('Parent',f, ...\r\n                'Position',[0.12 0.56 0.28 0.28]);\r\n            app.ReconstructedImageAxes = axes('Parent',f, ...\r\n                'Position',[0.60 0.56 0.28 0.28]);\r\n            app.MaskAxes = axes('Parent',f, ...\r\n                'Position',[0.12 0.16 0.28 0.28]);\r\n            app.ErrorImageAxes = axes('Parent',f, ...\r\n                'Position',[0.60 0.16 0.28 0.28]);\r\n            app.Slider = uicontrol('Style','slider', ...\r\n                'Value',app.NumDCTCoefficients\/64, ...\r\n                'Units','normalized', ...\r\n                'Position',[0.12 0.08 0.28 0.04], ...\r\n                'Callback',@(~,~,~) app.reactToSliderChange);<\/pre><pre>        end<\/pre><pre>        function reactToSliderChange(app)\r\n            v = get(app.Slider,'Value');\r\n            app.NumDCTCoefficients = round(64*v);\r\n            update(app);\r\n        end<\/pre><pre>        function update(app)\r\n            imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);\r\n            title(app.OriginalImageAxes,'Original Image');<\/pre><pre>            imshow(app.OriginalImage,'Parent',app.ReconstructedImageAxes);\r\n            title(app.ReconstructedImageAxes,'Reconstructed Image');<\/pre><pre>            imshow(zeros(size(app.OriginalImage)),'Parent',app.ErrorImageAxes);\r\n            title(app.ErrorImageAxes,'Error Image');<\/pre><pre>            imshow(zeros(size(app.OriginalImage)),'Parent',app.MaskAxes);\r\n            title(app.MaskAxes,'DCT Coefficient Mask');\r\n            drawnow;\r\n        end\r\n    end<\/pre><pre>end<\/pre><pre>function I = initialImage\r\npout = imread('pout.tif');\r\npout2 = pout(1:240,:);\r\nI = im2double(adapthisteq(pout2));\r\nend<\/pre><p>At this point I'll remind you of Dave Garrison's <a href=\"https:\/\/www.mathworks.com\/company\/newsletters\/articles\/writing-apps-in-matlab.html\">article<\/a> that I mentioned last time. This article teaches about how this kind of code works. I don't intend to repeat all of that article here. I'll just point out a few things.<\/p><p>Here's the function that runs when you launch the app.<\/p><pre>        function this_app = dctCompressionExample_v2\r\n            this_app.OriginalImage = initialImage;\r\n            layoutApp(this_app);\r\n            update(this_app);\r\n        end<\/pre><p><tt>initialImage<\/tt> is a little function I stuck at the bottom of the file. It's purpose is to create our sample image, which for the purpose of this simple DCT demonstration needs to be a multiple of 8-by-8 in size. (Plus, I threw in a call to <tt>adapthisteq<\/tt> because the original image has low contrast.)<\/p><pre>function I = initialImage\r\npout = imread('pout.tif');\r\npout2 = pout(1:240,:);\r\nI = im2double(adapthisteq(pout2));\r\nend<\/pre><p>Then there's the properties block.<\/p><pre>    properties (SetAccess = private)\r\n        OriginalImage\r\n        ReconstructedImage\r\n        ErrorImage\r\n        DCTCoefficientMask\r\n    end<\/pre><pre>    properties\r\n        NumDCTCoefficients = 10\r\n    end<\/pre><pre>    properties (Access = private)\r\n        Slider\r\n        OriginalImageAxes\r\n        ReconstructedImageAxes\r\n        ErrorImageAxes\r\n        MaskAxes\r\n    end<\/pre><p>Some of the properties, such as <tt>OriginalImage<\/tt>, I want to make accessible but read-only. Some of them, such as <tt>OriginalImageAxes<\/tt>, are private because they are only needed by the guts of the app. Notice that one of them, <tt>NumDCTCoefficients<\/tt>, is both readable <b>and<\/b> settable. I wanted to explore the idea of giving this app a little programmable interface so that you can write code to make it change.<\/p><p>I would like to make it so that the <tt>NumDCTCoefficients<\/tt> property changes when you drag the slider. Here's how to accomplish that:<\/p><pre>            app.Slider = uicontrol('Style','slider', ...\r\n                'Value',app.NumDCTCoefficients\/64, ...\r\n                'Units','normalized', ...\r\n                'Position',[0.12 0.08 0.28 0.04], ...\r\n                'Callback',@(~,~,~) app.reactToSliderChange);<\/pre><p>Setting the <tt>'Callback'<\/tt> property of the slider like this causes the app's function <tt>reactToSliderChange<\/tt> to get called whenever the slider is dragged. Here's what <tt>reactToSliderChange<\/tt> does:<\/p><pre>        function reactToSliderChange(app)\r\n            v = get(app.Slider,'Value');\r\n            app.NumDCTCoefficients = round(64*v);\r\n            update(app);\r\n        end<\/pre><p>Now we're starting to get a little interactivity going in our app.<\/p><p>That's about as far as I got this week. Next time we'll continue wiring things up and maybe start putting in some algorithmic DCT block processing code.<\/p>\r\n<div><ul><li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2013\/02\/08\/revisiting-dctdemo-part-1\/\">Revisiting dctdemo - part 1<\/a><\/li><li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2013\/02\/21\/revisiting-dctdemo-part-2\/\">Revisiting dctdemo - part 2<\/a><\/li><li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2013\/03\/21\/revisiting-dctdemo-part-3\/\">Revisiting dctdemo - part 3<\/a><\/li><li><a href=\"https:\/\/blogs.mathworks.com\/steve\/2013\/04\/12\/revisiting-dctdemo-part-4\/\">Revisiting dctdemo - part 4<\/a><\/li><\/ul><\/div>\r\n<script language=\"JavaScript\"> <!-- \r\n    function grabCode_ae0e4adbb7c2495998ab1c458bb46972() {\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='ae0e4adbb7c2495998ab1c458bb46972 ' + '##### ' + 'SOURCE BEGIN' + ' #####';\r\n        t2='##### ' + 'SOURCE END' + ' #####' + ' ae0e4adbb7c2495998ab1c458bb46972';\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 2013 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_ae0e4adbb7c2495998ab1c458bb46972()\"><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; R2012b<br><\/p><p class=\"footer\"><br>\r\n      Published with MATLAB&reg; R2012b<br><\/p><\/div><!--\r\nae0e4adbb7c2495998ab1c458bb46972 ##### SOURCE BEGIN #####\r\n%%\r\n% This is the second part of my plan to rewrite an Image Processing Toolbox\r\n% example from 20 years ago using more modern MATLAB language features.\r\n%\r\n% Recall the old app I'm trying to reinvent:\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2013\/dctdemo-screen-shot.png>>\r\n%\r\n% The idea is to experiment with the basic principles of DCT-based image\r\n% compression. I've decided that I don't want to copy this original layout\r\n% and functionality exactly. For one thing, computers (and MATLAB!) are a\r\n% lot faster than they were 20 years ago, and I think we really don't need\r\n% a separate \"Apply\" button.\r\n%\r\n% Here's my first attempt at sketching what I'd like to make this time\r\n% around.\r\n%\r\n% <<https:\/\/blogs.mathworks.com\/images\/steve\/2013\/dct-compression-sketch.jpg>>\r\n%\r\n% The truth, is, I'm making the code and these posts up as I go along. So\r\n% far I've only had a chance to get some of the initial pieces up and\r\n% working. But it's enough to start exploring some of the coding ideas.\r\n%\r\n% Here's what happens when I call the app class, which I've called (for\r\n% now) |dctCompressionExample_v2|.\r\n\r\napp = dctCompressionExample_v2\r\n\r\n%%\r\n% You can see I got some output in the Command Window, and I also got a\r\n% new figure on the screen.\r\n% \r\n% Here's the code so far.\r\n%\r\n%  classdef dctCompressionExample_v2 < handle\r\n%      \r\n%      properties (SetAccess = private)\r\n%          OriginalImage\r\n%          ReconstructedImage\r\n%          ErrorImage\r\n%          DCTCoefficientMask\r\n%      end\r\n%      \r\n%      properties\r\n%          NumDCTCoefficients = 10\r\n%      end\r\n%      \r\n%      properties (Access = private)\r\n%          Slider\r\n%          OriginalImageAxes\r\n%          ReconstructedImageAxes\r\n%          ErrorImageAxes\r\n%          MaskAxes\r\n%      end\r\n%      \r\n%      methods\r\n%          function this_app = dctCompressionExample_v2\r\n%              this_app.OriginalImage = initialImage;\r\n%              layoutApp(this_app);\r\n%              update(this_app);\r\n%          end\r\n%          \r\n%          function layoutApp(app)\r\n%              f = figure;\r\n%              app.OriginalImageAxes = axes('Parent',f, ...\r\n%                  'Position',[0.12 0.56 0.28 0.28]);\r\n%              app.ReconstructedImageAxes = axes('Parent',f, ...\r\n%                  'Position',[0.60 0.56 0.28 0.28]);\r\n%              app.MaskAxes = axes('Parent',f, ...\r\n%                  'Position',[0.12 0.16 0.28 0.28]);\r\n%              app.ErrorImageAxes = axes('Parent',f, ...\r\n%                  'Position',[0.60 0.16 0.28 0.28]);\r\n%              app.Slider = uicontrol('Style','slider', ...\r\n%                  'Value',app.NumDCTCoefficients\/64, ...\r\n%                  'Units','normalized', ...\r\n%                  'Position',[0.12 0.08 0.28 0.04], ...\r\n%                  'Callback',@(~,~,~) app.reactToSliderChange);\r\n%              \r\n%          end\r\n%          \r\n%          function reactToSliderChange(app)\r\n%              v = get(app.Slider,'Value');\r\n%              app.NumDCTCoefficients = round(64*v);\r\n%              update(app);\r\n%          end\r\n%          \r\n%          function update(app)\r\n%              imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);\r\n%              title(app.OriginalImageAxes,'Original Image');\r\n%              \r\n%              imshow(app.OriginalImage,'Parent',app.ReconstructedImageAxes);\r\n%              title(app.ReconstructedImageAxes,'Reconstructed Image');\r\n%              \r\n%              imshow(zeros(size(app.OriginalImage)),'Parent',app.ErrorImageAxes);\r\n%              title(app.ErrorImageAxes,'Error Image');\r\n%              \r\n%              imshow(zeros(size(app.OriginalImage)),'Parent',app.MaskAxes);\r\n%              title(app.MaskAxes,'DCT Coefficient Mask');\r\n%              drawnow;\r\n%          end\r\n%      end\r\n%      \r\n%  end\r\n%  \r\n%  function I = initialImage\r\n%  pout = imread('pout.tif');\r\n%  pout2 = pout(1:240,:);\r\n%  I = im2double(adapthisteq(pout2));\r\n%  end\r\n%\r\n% At this point I'll remind you of Dave Garrison's\r\n% <https:\/\/www.mathworks.com\/company\/newsletters\/articles\/writing-apps-in-matlab.html\r\n% article> that I mentioned last time. This article teaches about how this\r\n% kind of code works. I don't intend to repeat all of that article here.\r\n% I'll just point out a few things.\r\n%\r\n% Here's the function that runs when you launch the app.\r\n%\r\n%          function this_app = dctCompressionExample_v2\r\n%              this_app.OriginalImage = initialImage;\r\n%              layoutApp(this_app);\r\n%              update(this_app);\r\n%          end\r\n%\r\n% |initialImage| is a little function I stuck at the bottom of the file.\r\n% It's purpose is to create our sample image, which for the purpose of this\r\n% simple DCT demonstration needs to be a multiple of 8-by-8 in size. (Plus,\r\n% I threw in a call to |adapthisteq| because the original image has low\r\n% contrast.)\r\n%\r\n%  function I = initialImage\r\n%  pout = imread('pout.tif');\r\n%  pout2 = pout(1:240,:);\r\n%  I = im2double(adapthisteq(pout2));\r\n%  end\r\n%\r\n% Then there's the properties block. \r\n%\r\n%      properties (SetAccess = private)\r\n%          OriginalImage\r\n%          ReconstructedImage\r\n%          ErrorImage\r\n%          DCTCoefficientMask\r\n%      end\r\n%      \r\n%      properties\r\n%          NumDCTCoefficients = 10\r\n%      end\r\n%      \r\n%      properties (Access = private)\r\n%          Slider\r\n%          OriginalImageAxes\r\n%          ReconstructedImageAxes\r\n%          ErrorImageAxes\r\n%          MaskAxes\r\n%      end\r\n%\r\n% Some of the properties, such as |OriginalImage|, I want to make\r\n% accessible but read-only. Some of them, such as |OriginalImageAxes|, are\r\n% private because they are only needed by the guts of the app. Notice that\r\n% one of them, |NumDCTCoefficients|, is both readable *and* settable. I\r\n% wanted to explore the idea of giving this app a little programmable\r\n% interface so that you can write code to make it change.\r\n% \r\n% I would like to make it so that the |NumDCTCoefficients| property changes\r\n% when you drag the slider. Here's how to accomplish that:\r\n%\r\n%              app.Slider = uicontrol('Style','slider', ...\r\n%                  'Value',app.NumDCTCoefficients\/64, ...\r\n%                  'Units','normalized', ...\r\n%                  'Position',[0.12 0.08 0.28 0.04], ...\r\n%                  'Callback',@(~,~,~) app.reactToSliderChange);\r\n%\r\n% Setting the |'Callback'| property of the slider like this causes the\r\n% app's function |reactToSliderChange| to get called whenever the slider is\r\n% dragged. Here's what |reactToSliderChange| does:\r\n%\r\n%          function reactToSliderChange(app)\r\n%              v = get(app.Slider,'Value');\r\n%              app.NumDCTCoefficients = round(64*v);\r\n%              update(app);\r\n%          end\r\n%\r\n% Now we're starting to get a little interactivity going in our app.\r\n%\r\n% That's about as far as I got this week. Next time we'll continue wiring\r\n% things up and maybe start putting in some algorithmic DCT block\r\n% processing code.\r\n##### SOURCE END ##### ae0e4adbb7c2495998ab1c458bb46972\r\n-->","protected":false},"excerpt":{"rendered":"<div class=\"overview-image\"><img decoding=\"async\"  class=\"img-responsive\" src=\"https:\/\/blogs.mathworks.com\/images\/steve\/2013\/dctdemo_part2_01.png\" onError=\"this.style.display ='none';\" \/><\/div><p>\r\nThis is the second part of my plan to rewrite an Image Processing Toolbox example from 20 years ago using more modern MATLAB language features.Recall the old app I'm trying to reinvent: The idea is... <a class=\"read-more\" href=\"https:\/\/blogs.mathworks.com\/steve\/2013\/02\/21\/revisiting-dctdemo-part-2\/\">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":[134,595,981,390,76,36,188,52,979],"_links":{"self":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/766"}],"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=766"}],"version-history":[{"count":11,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/766\/revisions"}],"predecessor-version":[{"id":3813,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/posts\/766\/revisions\/3813"}],"wp:attachment":[{"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/media?parent=766"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/categories?post=766"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blogs.mathworks.com\/steve\/wp-json\/wp\/v2\/tags?post=766"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}