<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>Steve on Image Processing</title>
	
	<link>http://blogs.mathworks.com/steve</link>
	<description>Steve Eddins manages the Image &amp; Geospatial development team at The MathWorks and coauthored Digital Image Processing Using MATLAB. He writes here about image processing concepts, algorithm implementations, and MATLAB.</description>
	<lastBuildDate>Wed, 15 May 2013 17:55:36 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/SteveOnImageProcessing" /><feedburner:info uri="steveonimageprocessing" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>R2013a – Looking around in MATLAB</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/HCWwUcnJwls/</link>
		<comments>http://blogs.mathworks.com/steve/2013/05/15/r2013a-looking-around-in-matlab/#comments</comments>
		<pubDate>Wed, 15 May 2013 17:55:36 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=840</guid>
		<description><![CDATA[The first MathWorks general product release of the year, R2013a, shipped a couple of months ago. I've already mentioned it once here in my 12-Mar-2013 post about the new MATLAB unit test framework.With each new release, I peruse the release notes for MATLAB to see what things I find particularly interesting. (This helps me remember [...]]]></description>
				<content:encoded><![CDATA[
<div class="content"><p>The first MathWorks general product release of the year, <a href="http://www.mathworks.com/products/new_products/latest_features.html">R2013a</a>, shipped a couple of months ago. I've already mentioned it once here in my <a href="http://blogs.mathworks.com/steve/2013/03/12/matlab-software-testing-tools-old-and-new-r2013a/">12-Mar-2013 post</a> about the new MATLAB unit test framework.</p><p>With each new release, I peruse the release notes for MATLAB to see what things I find particularly interesting. (This helps me remember which product features have actually been released, as opposed to still being in development. My memory needs all the help it can get.)</p><p>The first thing to note is the reappearance of the table of contents for navigating in the Help Browser and in the online <a href="http://www.mathworks.com/help/matlab/index.html">Documentation Center</a>. This is a direct result of helpful feedback we received from many of you about the R2012b release.</p><p>My favorite "make-it-go-faster-without-sacrificing-accuracy" people (the MATLAB Math Team, that is) have been busy again. People with computers based on Intel or AMD chips using the AVX instruction set should see their calls to <tt>fft</tt> speed up. Anybody running <tt>permute</tt> on 3-D or higher-dimensional arrays should also get a nice boost. I've done a lot of development work related to image and scientific format support, so I know that a fast <tt>permute</tt> can be pretty useful when reading image and scientific data. That's because most of these formats store array elements in the file in a different order than MATLAB uses in memory.</p><p>In the small-but-nice category, the MATLAB Math Team also simplified a common programming pattern in my own neck of the woods (image processing). Specifically, it's a bit easier to initial an array of 0s or 1s whose type is based on existing array. Here's an example to illustrate:</p><pre class="codeinput">clear  <span class="comment">% Let's start with a fresh workspace.</span>
rgb = imread(<span class="string">'peppers.png'</span>);
imshow(rgb)
title(<span class="string">'Obligatory image screenshot'</span>)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/r2013a_matlab_01.jpg" alt=""> <p>Now I want a 100-by-100 matrix of 0s with the same data type as <tt>rgb</tt>.</p><pre class="codeinput">A = zeros(100,100,<span class="string">'like'</span>,rgb); <span class="comment">% Make a 100-by-100 matrix that's "like" rgb.</span>
whos
</pre><pre class="codeoutput">  Name        Size                Bytes  Class    Attributes

  A         100x100               10000  uint8              
  rgb       384x512x3            589824  uint8              

</pre><p>My developer friend Tom Bryan really "likes" this (ahem) because it enables much easier solutions to some common programming tasks for users of Fixed-Point Designer.</p><p>I have occasionally done a little web scripting in MATLAB, so it's nice to see <tt>urlread</tt> and <tt>urlwrite</tt> get a little love. These functions can now handle basic authentication via the <tt>'Authentication'</tt>, <tt>'Username'</tt>, and <tt>'Password'</tt> parameters.</p><p>Do you use a Mac? You can now write MPEG-4 H.264 files using <tt>VideoWriter</tt> (requires Mac OS 10.7 or later).</p><p>A couple of handy new string functions have appeared, <tt>strsplit</tt> and <tt>strjoin</tt>. Based on how often users have submitted their own versions to the <a href="http://www.mathworks.com/matlabcentral/fileexchange/">MATLAB Central File Exchange</a>, I'm sure these will be popular.</p><pre class="codeinput">out = strsplit(pwd,<span class="string">'\'</span>)
</pre><pre class="codeoutput">
out = 

    'B:'    'published'    '2013'

</pre><p>You can now do extrapolation with both scattered and gridded interpolation. For extrapolation with scattered interpolation, use the new <tt>scatteredInterpolant</tt>. Here's an example I lifted from the doc.</p><p>Query the interpolant at a single point outside the convex hull using nearest neighbor extrapolation.</p><p>Define a matrix of 200 random points.</p><pre class="codeinput">P = -2.5 + 5*gallery(<span class="string">'uniformdata'</span>,[200 2],0);
</pre><p>Sample an exponential function. These are the sample values for the interpolant.</p><pre class="codeinput">x = P(:,1);
y = P(:,2);
v = x.*exp(-x.^2-y.^2);
</pre><p>Create the interpolant, specifying linear interpolation and nearest neighbor extrapolation.</p><pre class="codeinput">F = scatteredInterpolant(P,v,<span class="string">'linear'</span>,<span class="string">'nearest'</span>)
</pre><pre class="codeoutput">
F = 

  scatteredInterpolant with properties:

                 Points: [200x2 double]
                 Values: [200x1 double]
                 Method: 'linear'
    ExtrapolationMethod: 'nearest'

</pre><p>Evaluate the interpolant outside the convex hull.</p><pre class="codeinput">vq = F(3.0,-1.5)
</pre><pre class="codeoutput">
vq =

    0.0031

</pre><p>Disable extrapolation and evaluate F at the same point.</p><pre class="codeinput">F.ExtrapolationMethod = <span class="string">'none'</span>;
vq = F(3.0,-1.5)
</pre><pre class="codeoutput">
vq =

   NaN

</pre><p>I encourage you to wander over to the R2013a release notes for <a href="http://www.mathworks.com/help/matlab/release-notes.html">MATLAB</a> or any other product that you use and see what's new that might be helpful to you.</p><p>There are also lots of new things in the image processing and computer vision worlds, of course. I'll look at those next time.</p><script language="JavaScript"> <!-- 
    function grabCode_e908749212e9435394509bf494f27583() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='e908749212e9435394509bf494f27583 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' e908749212e9435394509bf494f27583';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_e908749212e9435394509bf494f27583()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2013a<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2013a<br /></p></div><!--
e908749212e9435394509bf494f27583 ##### SOURCE BEGIN #####
%%
% The first MathWorks general product release of the year,
% <http://www.mathworks.com/products/new_products/latest_features.html
% R2013a>, shipped a couple of months ago. I've already mentioned it once
% here in my <http://blogs.mathworks.com/steve/2013/03/12/matlab-software-testing-tools-old-and-new-r2013a/
% 12-Mar-2013 post> about the new MATLAB unit test framework.
%
% With each new release, I peruse the release notes for MATLAB to see what
% things I find particularly interesting. (This helps me remember which
% product features have actually been released, as opposed to still being
% in development. My memory needs all the help it can get.)
%
% The first thing to note is the reappearance of the table of contents for
% navigating in the Help Browser and in the online 
% <http://www.mathworks.com/help/matlab/index.html Documentation Center>.
% This is a direct result of helpful feedback we received from many of you
% about the R2012b release.
%
% My favorite "make-it-go-faster-without-sacrificing-accuracy" people (the
% MATLAB Math Team, that is) have been busy again. People with computers
% based on Intel or AMD chips using the AVX instruction set should see
% their calls to |fft| speed up. Anybody running |permute| on 3-D or
% higher-dimensional arrays should also get a nice boost. I've done a lot
% of development work related to image and scientific format support, so I
% know that a fast |permute| can be pretty useful when reading image and
% scientific data. That's because most of these formats store array
% elements in the file in a different order than MATLAB uses in memory.
%
% In the small-but-nice category, the MATLAB Math Team also simplified a
% common programming pattern in my own neck of the woods (image
% processing). Specifically, it's a bit easier to initial an array of 0s or
% 1s whose type is based on existing array. Here's an example to
% illustrate:

clear  % Let's start with a fresh workspace.
rgb = imread('peppers.png');
imshow(rgb)
title('Obligatory image screenshot')

%%
% Now I want a 100-by-100 matrix of 0s with the same data type as |rgb|.

A = zeros(100,100,'like',rgb); % Make a 100-by-100 matrix that's "like" rgb.
whos

%%
% My developer friend Tom Bryan really "likes" this (ahem) because it
% enables much easier solutions to some common programming tasks for users
% of Fixed-Point Designer.

%%
% I have occasionally done a little web scripting in MATLAB, so it's nice
% to see |urlread| and |urlwrite| get a little love. These functions can
% now handle basic authentication via the |'Authentication'|, |'Username'|,
% and |'Password'| parameters.
%
% Do you use a Mac? You can now write MPEG-4 H.264 files using
% |VideoWriter| (requires Mac OS 10.7 or later).
%
% A couple of handy new string functions have appeared, |strsplit| and
% |strjoin|. Based on how often users have submitted their own versions to
% the <http://www.mathworks.com/matlabcentral/fileexchange/ 
% MATLAB Central File Exchange>, I'm sure these will be popular.

out = strsplit(pwd,'\')

%%
% You can now do extrapolation with both scattered and gridded
% interpolation. For extrapolation with scattered interpolation, use the
% new |scatteredInterpolant|. Here's an example I lifted from the doc.
%
% Query the interpolant at a single point outside the convex hull using
% nearest neighbor extrapolation.
%
% Define a matrix of 200 random points.
P = -2.5 + 5*gallery('uniformdata',[200 2],0);

%% 
% Sample an exponential function. These are the sample values for the
% interpolant.
x = P(:,1);
y = P(:,2);
v = x.*exp(-x.^2-y.^2);

%%
% Create the interpolant, specifying linear interpolation and nearest
% neighbor extrapolation.
F = scatteredInterpolant(P,v,'linear','nearest')

%%
% Evaluate the interpolant outside the convex hull.
vq = F(3.0,-1.5)

%%
% Disable extrapolation and evaluate F at the same point.
F.ExtrapolationMethod = 'none';
vq = F(3.0,-1.5)

%%
% I encourage you to wander over to the R2013a release notes for 
% <http://www.mathworks.com/help/matlab/release-notes.html MATLAB> or any
% other product that you use and see what's new that might be helpful to
% you.
%
% There are also lots of new things in the image processing and computer vision
% worlds, of course. I'll look at those next time.

##### SOURCE END ##### e908749212e9435394509bf494f27583
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/HCWwUcnJwls" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/05/15/r2013a-looking-around-in-matlab/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/05/15/r2013a-looking-around-in-matlab/</feedburner:origLink></item>
		<item>
		<title>JPEG and PNG – lossy and lossless image compression</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/nWM8uqZ7r90/</link>
		<comments>http://blogs.mathworks.com/steve/2013/05/02/jpeg-versus-png-lossy-and-lossless-image-compression/#comments</comments>
		<pubDate>Thu, 02 May 2013 20:45:41 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=835</guid>
		<description><![CDATA[I was reviewing enhancement requests recently when I came across this one: Add support for a 'Quality' parameter when using imwrite to write a PNG file, just like you can currently do when writing a JPEG file.Well, there is actually a pretty good reason why there is no 'Quality' parameter for writing PNG files, but [...]]]></description>
				<content:encoded><![CDATA[
<div class="content"><p>I was reviewing enhancement requests recently when I came across this one: <i>Add support for a 'Quality' parameter when using <tt>imwrite</tt> to write a PNG file, just like you can currently do when writing a JPEG file.</i></p><p>Well, there is actually a pretty good reason why there is no 'Quality' parameter for writing PNG files, but it's not an obvious reason unless you know more about the differences between various image compression methods.</p><p>A very important characteristic of a compression method is whether it is <i>lossless</i> or <i>lossy</i>. With a <i>lossless</i> compression method, the original data can be recovered exactly. When you make a "zip" file on your computer, this is what you certainly expect.</p><p>Here's an example: I can use <tt>gzip</tt> to compress the MATLAB script file I'm using for this blog post.</p><pre class="codeinput">gzip(<span class="string">'lossless_lossy.m'</span>);
dir(<span class="string">'lossless_lossy.*'</span>)
</pre><pre class="codeoutput">
lossless_lossy.m     lossless_lossy.m.gz  

</pre><p>Let's compare their sizes to see if the output of <tt>gzip</tt> is really compressed.</p><pre class="codeinput">d1 = dir(<span class="string">'lossless_lossy.m'</span>);
d1.bytes
</pre><pre class="codeoutput">
ans =

        4098

</pre><pre class="codeinput">d2 = dir(<span class="string">'lossless_lossy.m.gz'</span>);
d2.bytes
</pre><pre class="codeoutput">
ans =

        1785

</pre><p>Indeed, the compressed does actually have fewer bytes. Can we get the original file back exactly?</p><pre class="codeinput">gunzip(<span class="string">'lossless_lossy.m.gz'</span>,<span class="string">'./tmp'</span>)
isequal(fileread(<span class="string">'lossless_lossy.m'</span>),fileread(<span class="string">'./tmp/lossless_lossy.m'</span>))
</pre><pre class="codeoutput">
ans =

     1

</pre><p>Yes.</p><p>Let's switch to image formats. The PNG image format uses lossless compression. When you save image data to a PNG file, you can read the file back in and get back the original pixels, unchanged. For a sample image I'll use my <a href="http://www.mathworks.com/matlabcentral/fileexchange/35961-zone-plate-test-image/content/imzoneplate.m">imzoneplate function</a> on the MATLAB Central File Exchange.</p><pre class="codeinput">I = im2uint8(imzoneplate);
imshow(I)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/lossless_lossy_01.png" alt=""> <p>Let's write <tt>I</tt> out to a PNG file, read it back in, and see if the pixels are the same.</p><pre class="codeinput">imwrite(I,<span class="string">'zoneplate.png'</span>);
I2 = imread(<span class="string">'zoneplate.png'</span>);
isequal(I,I2)
</pre><pre class="codeoutput">
ans =

     1

</pre><p>OK, now let's try the same experiment using JPEG.</p><pre class="codeinput">imwrite(I,<span class="string">'zoneplate.jpg'</span>)
I2j = imread(<span class="string">'zoneplate.jpg'</span>);
isequal(I,I2j)
</pre><pre class="codeoutput">
ans =

     0

</pre><p>No, the pixels are not equal! It turns out the JPEG is a <i>lossy</i> image compression format. (Full disclosure: there is a lossless variant of JPEG, but it is rarely used.)</p><p>Why in the world would we use a compression format that doesn't preserve the original data? Because by giving up on exact data recovery and by taking advantage of properties of human visual perception, we can make the stored file a lot smaller. Let's compare the file sizes of the PNG file with the JPEG file.</p><pre class="codeinput">z1 = dir(<span class="string">'zoneplate.png'</span>);
num_bytes_png = z1.bytes
</pre><pre class="codeoutput">
num_bytes_png =

      218864

</pre><pre class="codeinput">z2 = dir(<span class="string">'zoneplate.jpg'</span>);
num_bytes_jpeg = z2.bytes
</pre><pre class="codeoutput">
num_bytes_jpeg =

       72660

</pre><p>The JPEG file is only one-third the size of the PNG file! But it looks almost exactly the same.</p><pre class="codeinput">imshow(<span class="string">'zoneplate.jpg'</span>)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/lossless_lossy_02.png" alt=""> <p>So, what about that <tt>'Quality'</tt> parameter that I mentioned at the top of today's post? It turns out that we can make the JPEG file even smaller if we are willing to put up with some visible distortion in the image. Let's try a quality factor of 25. (The default is 75 on a scale of 0 to 100.)</p><pre class="codeinput">imwrite(I,<span class="string">'zoneplate_25.jpg'</span>,<span class="string">'Quality'</span>,25)
I2j_25 = imread(<span class="string">'zoneplate_25.jpg'</span>);
imshow(I2j_25)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/lossless_lossy_03.png" alt=""> <p>You can see some distortion, especially around the high-frequency part of the pattern. How about the file size?</p><pre class="codeinput">z3 = dir(<span class="string">'zoneplate_25.jpg'</span>);
z3.bytes
</pre><pre class="codeoutput">
ans =

       39544

</pre><p>That's about 54% of the size of the zoneplate.jpg.</p><p>Sometimes people think they can get "lossless JPEG" by using a <tt>'Quality'</tt> factor of 100, but unfortunately that isn't the case. Let's check it:</p><pre class="codeinput">imwrite(I,<span class="string">'zoneplate_100.jpg'</span>,<span class="string">'Quality'</span>,100)
I2j_100 = imread(<span class="string">'zoneplate_100.jpg'</span>);
isequal(I,I2j_100)
</pre><pre class="codeoutput">
ans =

     0

</pre><p>So there you go -- that's why there's no <tt>'Quality'</tt> parameter when writing PNG files. PNG files are always perfect!</p><p>When I write blog posts, sometimes I use PNG image files and sometimes I use JPEG. My choice is based on what kind of graphics I have in that particular post. And that's a blog topic for another day.</p><script language="JavaScript"> <!-- 
    function grabCode_12318cdcbb924e14ab145765df1dcbab() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='12318cdcbb924e14ab145765df1dcbab ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 12318cdcbb924e14ab145765df1dcbab';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_12318cdcbb924e14ab145765df1dcbab()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2013a<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2013a<br /></p></div><!--
12318cdcbb924e14ab145765df1dcbab ##### SOURCE BEGIN #####
%%
% I was reviewing enhancement requests recently when I came across this
% one: _Add support for a 'Quality' parameter when using |imwrite| to write
% a PNG file, just like you can currently do when writing a JPEG file._
%
% Well, there is actually a pretty good reason why there is no 'Quality'
% parameter for writing PNG files, but it's not an obvious reason unless
% you know more about the differences between various image compression
% methods.
%
% A very important characteristic of a compression method is whether it is
% _lossless_ or _lossy_. With a _lossless_ compression method, the original
% data can be recovered exactly. When you make a "zip" file on your
% computer, this is what you certainly expect. 
%
% Here's an example: I can use |gzip| to compress the MATLAB script file
% I'm using for this blog post.

gzip('lossless_lossy.m');
dir('lossless_lossy.*')

%%
% Let's compare their sizes to see if the output of |gzip| is really
% compressed.

d1 = dir('lossless_lossy.m');
d1.bytes

%%

d2 = dir('lossless_lossy.m.gz');
d2.bytes

%%
% Indeed, the compressed does actually have fewer bytes. Can we get the
% original file back exactly?

gunzip('lossless_lossy.m.gz','./tmp')
isequal(fileread('lossless_lossy.m'),fileread('./tmp/lossless_lossy.m'))

%%
% Yes.
%
% Let's switch to image formats. The PNG image format uses lossless
% compression. When you save image data to a PNG file, you can read the
% file back in and get back the original pixels, unchanged. For a sample
% image I'll use my
% <http://www.mathworks.com/matlabcentral/fileexchange/35961-zone-plate-test-image/content/imzoneplate.m
% imzoneplate function> on the MATLAB Central File Exchange.

I = im2uint8(imzoneplate);
imshow(I)

%%
% Let's write |I| out to a PNG file, read it back in, and see if the pixels
% are the same.

imwrite(I,'zoneplate.png');
I2 = imread('zoneplate.png');
isequal(I,I2)

%%
% OK, now let's try the same experiment using JPEG.

imwrite(I,'zoneplate.jpg')
I2j = imread('zoneplate.jpg');
isequal(I,I2j)

%%
% No, the pixels are not equal! It turns out the JPEG is a _lossy_ image
% compression format. (Full disclosure: there is a lossless variant of
% JPEG, but it is rarely used.)
%
% Why in the world would we use a compression format that doesn't preserve
% the original data? Because by giving up on exact data recovery and by
% taking advantage of properties of human visual perception, we can make
% the stored file a lot smaller. Let's compare the file sizes of the PNG
% file with the JPEG file.

z1 = dir('zoneplate.png');
num_bytes_png = z1.bytes

%%

z2 = dir('zoneplate.jpg');
num_bytes_jpeg = z2.bytes

%%
% The JPEG file is only one-third the size of the PNG file! But it looks
% almost exactly the same.

imshow('zoneplate.jpg')

%%
% So, what about that |'Quality'| parameter that I mentioned at the top of
% today's post? It turns out that we can make the JPEG file even smaller if
% we are willing to put up with some visible distortion in the image. Let's
% try a quality factor of 25. (The default is 75 on a scale of 0 to 100.)

imwrite(I,'zoneplate_25.jpg','Quality',25)
I2j_25 = imread('zoneplate_25.jpg');
imshow(I2j_25)

%%
% You can see some distortion, especially around the high-frequency part of
% the pattern. How about the file size?

z3 = dir('zoneplate_25.jpg');
z3.bytes

%%
% That's about 54% of the size of the zoneplate.jpg.
%
% Sometimes people think they can get "lossless JPEG" by using a
% |'Quality'| factor of 100, but unfortunately that isn't the case. Let's
% check it:

imwrite(I,'zoneplate_100.jpg','Quality',100)
I2j_100 = imread('zoneplate_100.jpg');
isequal(I,I2j_100)

%%
% So there you go REPLACE_WITH_DASH_DASH that's why there's no |'Quality'| parameter when
% writing PNG files. PNG files are always perfect!
%
% When I write blog posts, sometimes I use PNG image files and sometimes I
% use JPEG. My choice is based on what kind of graphics I have in that
% particular post. And that's a blog topic for another day.
##### SOURCE END ##### 12318cdcbb924e14ab145765df1dcbab
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/nWM8uqZ7r90" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/05/02/jpeg-versus-png-lossy-and-lossless-image-compression/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/05/02/jpeg-versus-png-lossy-and-lossless-image-compression/</feedburner:origLink></item>
		<item>
		<title>Revisiting dctdemo – part 4</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/9Loy5jz1MAs/</link>
		<comments>http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/#comments</comments>
		<pubDate>Fri, 12 Apr 2013 13:41:36 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=825</guid>
		<description><![CDATA[This is the fourth and last part of my plan (my evil plan?) to rewrite an Image Processing Toolbox example from 20 years ago using more modern MATLAB language features. I got the idea from Dave Garrison's recent article on writing MATLAB apps.Here's the old app I'm trying to reinvent: And here's what I had [...]]]></description>
				<content:encoded><![CDATA[
<div class="content"><p>This is the fourth and last part of my plan (my evil plan?) to rewrite an Image Processing Toolbox example from 20 years ago using more modern MATLAB language features. I got the idea from Dave Garrison's <a href="http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html">recent article</a> on writing MATLAB apps.</p><p>Here's the old app I'm trying to reinvent:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png" alt=""> </p><p>And here's what I had working <a href="http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/">last time</a>:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dct-compression-example-v3.png" alt=""> </p><p>There are two things I want to wrap up before calling it good enough:</p><div><ul><li>Implement the display of the DCT coefficient mask (lower left of app)</li><li>Allow user to control the number of DCT coefficients by setting the <tt>NumDCTCoefficients</tt> property of the app.</li></ul></div><p>First let's get the DCT coefficient mask display working. Recall that last time I added a function to compute the reconstructed image, given the desired number of DCT coefficients. I'll add a second output argument to that function in order to return the DCT coefficient mask. Here's the code. The only changes are on the first line (to define the additional output argument) and the last three lines (to compute the mask).</p><pre>function [I2,mask] = reconstructImage(I,n)
% Reconstruct the image from n of the DCT coefficients in each 8-by-8
% block. Select the n coefficients with the largest variance across the
% image. Second output argument is the 8-by-8 DCT coefficient mask.</pre><pre>% Compute 8-by-8 block DCTs.
f = @(block) dct2(block.data);
A = blockproc(I,[8 8],f);</pre><pre>% Compute DCT coefficient variances and decide
% which to keep.
B = im2col(A,[8 8],'distinct')';
vars = var(B);
[~,idx] = sort(vars,'descend');
keep = idx(1:n);</pre><pre>% Zero out the DCT coefficients we are not keeping.
B2 = zeros(size(B));
B2(:,keep) = B(:,keep);</pre><pre>% Reconstruct image using 8-by-8 block inverse
% DCTs.
C = col2im(B2',[8 8],size(I),'distinct');
finv = @(block) idct2(block.data);
I2 = blockproc(C,[8 8],finv);</pre><pre>mask = false(8,8);
mask(keep) = true;
end</pre><p>Next I need some code to visualize the coefficient mask. I want to display it as image with gray lines drawn between the mask pixels. So I added a local function called <tt>displayCoefficientMask</tt>:</p><pre>function displayCoefficientMask(mask,ax)
imshow(mask,'Parent',ax)
for k = 0.5:1.0:8.5
    line('XData',[0.5 8.5], ...
        'YData',[k k], ...
        'Color',[0.6 0.6 0.6], ...
        'LineWidth',2, ...
        'Clipping','off', ...
        'Parent',ax);
    line('XData',[k k],...
        'YData',[0.5 8.5],...
        'Color',[0.6 0.6 0.6], ...
        'LineWidth',2,...
        'Clipping','off', ...
        'Parent',ax);
end
title(ax,'DCT Coefficient Mask')
end</pre><p>The last step is to call <tt>displayCoefficientMask</tt> from the <tt>update</tt> method (which gets called whenever the slider is moved). In the code below, I have modified the call to <tt>reconstructImage</tt> to use two output arguments in order to get the mask; I have assigned the various app properties; and I have added the call to <tt>displayCoefficientMask</tt> at the end.</p><pre>function update(app)
% Update the computation
[recon_image,mask] = reconstructImage(app.OriginalImage, ...
    app.NumDCTCoefficients);</pre><pre>diff_image = imabsdiff(app.OriginalImage, recon_image);</pre><pre>% Update the app properties
app.ReconstructedImage = recon_image;
app.ErrorImage = diff_image;
app.DCTCoefficientMask = mask;</pre><pre>% Update the display
imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);
title(app.OriginalImageAxes,'Original Image');</pre><pre>imshow(recon_image,'Parent',app.ReconstructedImageAxes);
title(app.ReconstructedImageAxes,'Reconstructed Image');</pre><pre>imshow(diff_image,[],'Parent',app.ErrorImageAxes);
title(app.ErrorImageAxes,'Error Image');</pre><pre>displayCoefficientMask(mask,app.MaskAxes);</pre><pre>drawnow;
end</pre><p>Here's the result with the DCT coefficient mask visualization included:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dct-compression-example-v4.png" alt=""> </p><p>The last thing I want to do with this little app is to allow users to set the app's <tt>NumDCTCoefficients</tt> property from the command line and to have the app automatically update. To do this, I'll make a couple of changes to the <tt>NumDCTCoefficients</tt> property. First, I'll make it a <i>dependent</i> property. Instead of being stored independently, this property will be computed on-the-fly from slider setting whenever it is queried. That requires that I define a <a href="http://www.mathworks.com/help/matlab/matlab_oop/property-access-methods.html"><i>property get method</i></a> that computes the property's value on demand. And last I'll need a <i>property set method</i> that defines what actions should be taken whenever the user sets the property.</p><p>Here's the modified <tt>property</tt> block that indicates that <tt>NumDCTCoefficients</tt> is a dependent property.</p><pre>properties (Dependent)
    NumDCTCoefficients
end</pre><p>And here are the get and set functions for <tt>NumDCTCoefficients</tt>. The get function computes the number on-the-fly based on the current slider position. The set function modifies the slider position and then calls the <tt>update</tt> method to recompute and redisplay everything.</p><pre>function value = get.NumDCTCoefficients(app)
    value = round(get(app.Slider,'Value') * 64);
end</pre><pre>function set.NumDCTCoefficients(app,num_coefficients)
    set(app.Slider,'Value',num_coefficients/64)
    update(app);
end</pre><p>Here's an example of this interaction.</p><pre class="codeinput">app = dctCompressionExample_v5
</pre><pre class="codeoutput">
app = 

  dctCompressionExample_v5 with properties:

         OriginalImage: [240x240 double]
    ReconstructedImage: [240x240 double]
            ErrorImage: [240x240 double]
    DCTCoefficientMask: [8x8 logical]
    NumDCTCoefficients: 3

</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo_part4_01.png" alt=""> <p>I can see the DCT coefficient mask on the app, but I can also look at the <tt>DCTCoefficientMask</tt> property.</p><pre class="codeinput">app.DCTCoefficientMask
</pre><pre class="codeoutput">
ans =

     1     1     0     0     0     0     0     0
     1     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0
     0     0     0     0     0     0     0     0

</pre><p>And I can set the <tt>NumDCTCoefficients</tt> property, which causes the app to update.</p><pre class="codeinput">app.NumDCTCoefficients = 1;
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo_part4_02.png" alt=""> <p>OK, I think that's enough to get all the basic ideas. If you want to play around with the final version of the code for this blog post, you can download it from <a href="http://blogs.mathworks.com/images/steve/2013/dctCompressionExample_v5.m">here</a>.</p><div><ul><li><a href="http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/">Revisiting dctdemo - part 1</a></li><li><a href="http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/">Revisiting dctdemo - part 2</a></li><li><a href="http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/">Revisiting dctdemo - part 3</a></li><li><a href="http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/">Revisiting dctdemo - part 4</a></li></ul></div><script language="JavaScript"> <!-- 
    function grabCode_ca80ad834362412ca00fdfb72ba253d6() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='ca80ad834362412ca00fdfb72ba253d6 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' ca80ad834362412ca00fdfb72ba253d6';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_ca80ad834362412ca00fdfb72ba253d6()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2013a<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2013a<br /></p></div><!--
ca80ad834362412ca00fdfb72ba253d6 ##### SOURCE BEGIN #####
%%
% This is the fourth and last part of my plan (my evil plan?) to rewrite an
% Image Processing Toolbox example from 20 years ago using more modern
% MATLAB language features. I got the idea from Dave Garrison's
% <http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html
% recent article> on writing MATLAB apps.
%
% Here's the old app I'm trying to reinvent:
%
% <<http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png>>
%
% And here's what I had working <http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/ 
% last time>:
%
% <<http://blogs.mathworks.com/images/steve/2013/dct-compression-example-v3.png>>
%
% There are two things I want to wrap up before calling it good enough:
%
% * Implement the display of the DCT coefficient mask (lower left of app)
% * Allow user to control the number of DCT coefficients by setting the
% |NumDCTCoefficients| property of the app.
%
% First let's get the DCT coefficient mask display working. Recall that
% last time I added a function to compute the reconstructed image, given
% the desired number of DCT coefficients. I'll add a second output argument
% to that function in order to return the DCT coefficient mask. Here's the
% code. The only changes are on the first line (to define the additional
% output argument) and the last three lines (to compute the mask).
%
%  function [I2,mask] = reconstructImage(I,n)
%  % Reconstruct the image from n of the DCT coefficients in each 8-by-8
%  % block. Select the n coefficients with the largest variance across the
%  % image. Second output argument is the 8-by-8 DCT coefficient mask.
%  
%  % Compute 8-by-8 block DCTs.
%  f = @(block) dct2(block.data);
%  A = blockproc(I,[8 8],f);
%  
%  % Compute DCT coefficient variances and decide
%  % which to keep.
%  B = im2col(A,[8 8],'distinct')';
%  vars = var(B);
%  [~,idx] = sort(vars,'descend');
%  keep = idx(1:n);
%  
%  % Zero out the DCT coefficients we are not keeping.
%  B2 = zeros(size(B));
%  B2(:,keep) = B(:,keep);
%  
%  % Reconstruct image using 8-by-8 block inverse
%  % DCTs.
%  C = col2im(B2',[8 8],size(I),'distinct');
%  finv = @(block) idct2(block.data);
%  I2 = blockproc(C,[8 8],finv);
%  
%  mask = false(8,8);
%  mask(keep) = true;
%  end
%
% Next I need some code to visualize the coefficient mask. I want to
% display it as image with gray lines drawn between the mask pixels. So I
% added a local function called |displayCoefficientMask|:
%
%  function displayCoefficientMask(mask,ax)
%  imshow(mask,'Parent',ax)
%  for k = 0.5:1.0:8.5
%      line('XData',[0.5 8.5], ...
%          'YData',[k k], ...
%          'Color',[0.6 0.6 0.6], ...
%          'LineWidth',2, ...
%          'Clipping','off', ...
%          'Parent',ax);
%      line('XData',[k k],...
%          'YData',[0.5 8.5],...
%          'Color',[0.6 0.6 0.6], ...
%          'LineWidth',2,...
%          'Clipping','off', ...
%          'Parent',ax);
%  end
%  title(ax,'DCT Coefficient Mask')
%  end
%
% The last step is to call |displayCoefficientMask| from the |update|
% method (which gets called whenever the slider is moved). In the code
% below, I have modified the call to |reconstructImage| to use two output
% arguments in order to get the mask; I have assigned the various app
% properties; and I have added the call to |displayCoefficientMask| at the
% end.
%
%  function update(app)
%  % Update the computation
%  [recon_image,mask] = reconstructImage(app.OriginalImage, ...
%      app.NumDCTCoefficients);
%  
%  diff_image = imabsdiff(app.OriginalImage, recon_image);
%  
%  % Update the app properties
%  app.ReconstructedImage = recon_image;
%  app.ErrorImage = diff_image;
%  app.DCTCoefficientMask = mask;
%  
%  % Update the display
%  imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);
%  title(app.OriginalImageAxes,'Original Image');
%  
%  imshow(recon_image,'Parent',app.ReconstructedImageAxes);
%  title(app.ReconstructedImageAxes,'Reconstructed Image');
%  
%  imshow(diff_image,[],'Parent',app.ErrorImageAxes);
%  title(app.ErrorImageAxes,'Error Image');
%  
%  displayCoefficientMask(mask,app.MaskAxes);
%  
%  drawnow;
%  end
%
% Here's the result with the DCT coefficient mask visualization included:
%
% <<http://blogs.mathworks.com/images/steve/2013/dct-compression-example-v4.png>>
%
% The last thing I want to do with this little app is to allow users to set
% the app's |NumDCTCoefficients| property from the command line and to have
% the app automatically update. To do this, I'll make a couple of changes
% to the |NumDCTCoefficients| property. First, I'll make it a _dependent_
% property. Instead of being stored independently, this property will be
% computed on-the-fly from slider setting whenever it is queried. That
% requires that I define a 
% <http://www.mathworks.com/help/matlab/matlab_oop/property-access-methods.html 
% _property get method_> that computes the property's value on demand. And
% last I'll need a _property set method_ that defines what actions should
% be taken whenever the user sets the property.
%
% Here's the modified |property| block that indicates that
% |NumDCTCoefficients| is a dependent property.
%
%  properties (Dependent)
%      NumDCTCoefficients
%  end
%
% And here are the get and set functions for |NumDCTCoefficients|. The get
% function computes the number on-the-fly based on the current slider
% position. The set function modifies the slider position and then calls
% the |update| method to recompute and redisplay everything.
%
%  function value = get.NumDCTCoefficients(app)
%      value = round(get(app.Slider,'Value') * 64);
%  end
%  
%  function set.NumDCTCoefficients(app,num_coefficients)
%      set(app.Slider,'Value',num_coefficients/64)
%      update(app);
%  end
%
% Here's an example of this interaction.

app = dctCompressionExample_v5

%%
% I can see the DCT coefficient mask on the app, but I can also look at the
% |DCTCoefficientMask| property.

app.DCTCoefficientMask

%%
% And I can set the |NumDCTCoefficients| property, which causes the app to
% update.

app.NumDCTCoefficients = 1;

%%
% OK, I think that's enough to get all the basic ideas. If you want to play
% around with the final version of the code for this blog post, you can
% download it from
% <http://blogs.mathworks.com/images/steve/2013/dctCompressionExample_v5.m
% here>.
%
% * <http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/ Revisiting dctdemo - part 1>
% * <http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/ Revisiting dctdemo - part 2>
% * <http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/ Revisiting dctdemo - part 3>
% * <http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/ Revisiting dctdemo - part 4>

##### SOURCE END ##### ca80ad834362412ca00fdfb72ba253d6
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/9Loy5jz1MAs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/</feedburner:origLink></item>
		<item>
		<title>Cluster-based image display</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/340EPqfkTRY/</link>
		<comments>http://blogs.mathworks.com/steve/2013/04/01/cluster-based-image-display/#comments</comments>
		<pubDate>Mon, 01 Apr 2013 10:00:28 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=814</guid>
		<description><![CDATA[Although this is the time of year that I normally mention some of the new features from the "a" release, today I thought I would focus on a feature added several releases ago that I think deserves more attention: parallel cluster-based image display. I can't remember exactly when this was released; I think it might [...]]]></description>
				<content:encoded><![CDATA[<div class="content"><p>Although this is the time of year that I normally mention some of the new features from the "a" release, <a href="http://en.wikipedia.org/wiki/April_Fools'_Day">today</a> I thought I would focus on a feature added several releases ago that I think deserves more attention: parallel cluster-based image display. I can't remember exactly when this was released; I think it might have been R2011c.</p><p>Anyway, it turns out image display speed can be dramatically increased if we exploit the capabilities of today's massive parallel computing clusters. You start by opening a MATLAB pool from your desktop session using the Parallel Computing Toolbox function <tt>matlabpool</tt>. The Parallel Computing Toolbox has a new cluster profile that makes it easy to set things up for fast image display:</p><pre>matlabpool image-display</pre><p>Once the pool is configured, then the Image Processing Toolbox function <tt>imshow</tt> automatically uses the workers in the pool.</p><p>Let's try it with my blog author picture:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/Eddins_Steve_140x211.jpg" alt=""> </p><p>(I'm writing this blog post at home, so for a cluster I'll be using my home-brew video game console, which runs on a cluster of 128 <a href="http://en.wikipedia.org/wiki/TRS-80">TRS-80s</a>.)</p><pre>imshow</pre><p>Here's what the display looks like on worker #37:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/cluster-37.png" alt=""> </p><p>And here is the display on worker #92:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/cluster-92.png" alt=""> </p><p>If you look carefully, you can see that the pixel block is not exactly the same size on the two workers. That's because of the automatic worker load balancing feature. Way cool!</p><p>Let's get down to some numbers. Specifically, I was interested to see how well image display performance scales with the number of workers. I used my function <a href="http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function"><tt>timeit</tt></a> to measure the display speed as I varied the number of workers. The plot below is "normalized speed-up." That is, 1 is the image display speed for normal MATLAB, with no use of the Parallel Computing Toolbox.</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/perf-graph.png" alt=""> </p><p>As you can see, we get almost perfectly linear scaling with the number of workers. (I'm not sure what's going on with that blip on the left. I think it might have been caused by a bad tape unit on worker #25.)</p><p>So, Parallel Computing Toolbox users, please give this a try and let us know about your experience!</p><p>Before I wrap it up for today, I can't resist giving a hint about future development directions. (Long-time readers know how much MathWorks loves to preannounce features.) We recently got our hands on one of the experimental new superfluidic clusters. Early indications are that we'll be able to get image display speed to scale with the <b>square</b> of the number of workers!  Woo-hoo!</p><script language="JavaScript"> <!-- 
    function grabCode_17b585bcd58b412385e25985ca4e9738() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='17b585bcd58b412385e25985ca4e9738 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 17b585bcd58b412385e25985ca4e9738';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_17b585bcd58b412385e25985ca4e9738()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2013a<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2013a<br /></p></div><!--
17b585bcd58b412385e25985ca4e9738 ##### SOURCE BEGIN #####
%%
% Although this is the time of year that I normally mention some of the new
% features from the "a" release,
% <http://en.wikipedia.org/wiki/April_Fools'_Day today> I thought I would
% focus on a feature added several releases ago that I think deserves more
% attention: parallel cluster-based image display. I can't remember exactly
% when this was released; I think it might have been R2011c.
%
% Anyway, it turns out image display speed can be dramatically increased if
% we exploit the capabilities of today's massive parallel computing
% clusters. You start by opening a MATLAB pool from your desktop session
% using the Parallel Computing Toolbox function |matlabpool|. The Parallel
% Computing Toolbox has a new cluster profile that makes it easy to set
% things up for fast image display:
%
%  matlabpool image-display
%
% Once the pool is configured, then the Image Processing Toolbox function
% |imshow| automatically uses the workers in the pool.
%
% Let's try it with my blog author picture:
%
% <<http://blogs.mathworks.com/images/steve/Eddins_Steve_140x211.jpg>>
%
% (I'm writing this blog post at home, so for a cluster I'll be using my
% home-brew video game console, which runs on a cluster of 128 
% <http://en.wikipedia.org/wiki/TRS-80 TRS-80s>.)
%
%  imshow
%
% Here's what the display looks like on worker #37:
%
% <<http://blogs.mathworks.com/images/steve/2013/cluster-37.png>>
%
% And here is the display on worker #92:
%
% <<http://blogs.mathworks.com/images/steve/2013/cluster-92.png>>
%
% If you look carefully, you can see that the pixel block is not exactly
% the same size on the two workers. That's because of the automatic worker
% load balancing feature. Way cool!
%
% Let's get down to some numbers. Specifically, I was interested to see how
% well image display performance scales with the number of workers. I used
% my function <http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function 
% |timeit|> to measure the display speed as I varied the number of workers.
% The plot below is "normalized speed-up." That is, 1 is the image display
% speed for normal MATLAB, with no use of the Parallel Computing Toolbox.
%
% <<http://blogs.mathworks.com/images/steve/2013/perf-graph.png>>
%
% As you can see, we get almost perfectly linear scaling with the number of
% workers. (I'm not sure what's going on with that blip on the left. I
% think it might have been caused by a bad tape unit on worker #25.)
%
% So, Parallel Computing Toolbox users, please give this a try and let us
% know about your experience!
%
% Before I wrap it up for today, I can't resist giving a hint about future
% development directions. (Long-time readers know how much MathWorks loves
% to preannounce features.) We recently got our hands on one of the
% experimental new superfluidic clusters. Early indications are that we'll
% be able to get image display speed to scale with the *square* of the
% number of workers!  Woo-hoo!

##### SOURCE END ##### 17b585bcd58b412385e25985ca4e9738
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/340EPqfkTRY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/04/01/cluster-based-image-display/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/04/01/cluster-based-image-display/</feedburner:origLink></item>
		<item>
		<title>Revisiting dctdemo – part 3</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/c0gCy6KbXzw/</link>
		<comments>http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/#comments</comments>
		<pubDate>Thu, 21 Mar 2013 20:14:57 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=809</guid>
		<description><![CDATA[This is the third part of my plan to rewrite an Image Processing Toolbox example from 20 years ago using more modern MATLAB language features. I got the idea from Dave Garrison's recent article on writing MATLAB apps.Here's the old app I'm trying to reinvent: And here's what I had working the last time: The [...]]]></description>
				<content:encoded><![CDATA[<div class="content"><p>This is the third part of my plan to rewrite an Image Processing Toolbox example from 20 years ago using more modern MATLAB language features. I got the idea from Dave Garrison's <a href="http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html">recent article</a> on writing MATLAB apps.</p><p>Here's the old app I'm trying to reinvent:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png" alt=""> </p><p>And here's what I had working the last time:</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dct-compression-v2.png" alt=""> </p><p>The code isn't doing any actual DCT computations yet. The idea is to compute 8-by-8 block DCTs, zero out the least significant DCT coefficients of each block, and then reconstruct the image by computing the inverse DCT of each 8-by-8 block.</p><p>Let me show how this will work on the sample image I'm using for the app:</p><pre class="codeinput">pout = imread(<span class="string">'pout.tif'</span>);
pout2 = pout(1:240,:);
I = im2double(adapthisteq(pout2));
imshow(I)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo_part3_01.png" alt=""> <p>First, use <tt>blockproc</tt> to compute the 8-by-8 2-D DCTs.</p><pre class="codeinput">f = @(block) dct2(block.data);
A = blockproc(I,[8 8],f);
imshow(A,[])
title(<span class="string">'DCT coefficients'</span>)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo_part3_02.png" alt=""> <p>Second, I want to compute the variances of each of the 64 coefficients. That is, compute the variance of the (1,1) DCT coefficients from each block, the variance of the (1,2) DCT coefficients from each block, and so on. I'll use the computed variances to determine which DCT coefficients to keep and which to zero out. To do this, I'll rearrange the elements from the previous step so that the corresponding DCT coefficients are together in the columns of a 64-column matrix.</p><pre class="codeinput">B = im2col(A,[8 8],<span class="string">'distinct'</span>)';
vars = var(B);
plot(vars)
title(<span class="string">'Variances of the 64 DCT coefficients'</span>)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo_part3_03.png" alt=""> <p>Next, suppose we want to keep the 3 block DCT coefficients with the highest variances. I'll use <tt>sort</tt> to figure out which ones to keep.</p><pre class="codeinput">[~,idx] = sort(vars,<span class="string">'descend'</span>);
keep = idx(1:3)
</pre><pre class="codeoutput">
keep =

     1     9     2

</pre><p>For an 8-by-8 block of DCT coefficients, index values 1, 9, and 2 correspond to the upper-left DCT coefficient and the two coefficients just the right and down from it. Let's keep just those coefficients.</p><pre class="codeinput">B2 = zeros(size(B));
B2(:,keep) = B(:,keep);
</pre><p>Now I'll rearrange the columns back into blocks and reconstruct the image by computing the inverse DCT of each block.</p><pre class="codeinput">C = col2im(B2',[8 8],size(I),<span class="string">'distinct'</span>);
finv = @(block) idct2(block.data);
D = blockproc(C,[8 8],finv);
imshow(D)
title(<span class="string">'Image reconstructed from 3 DCT coefficients per block'</span>)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo_part3_04.png" alt=""> <p>This algorithm code into a local function to go at the bottom of my app code file, like this:</p><pre>function I2 = reconstructImage(I,n)
% Reconstruct the image from n of the DCT coefficients in each 8-by-8
% block. Select the n coefficients with the largest variance across the
% image.</pre><pre>% Compute 8-by-8 block DCTs.
f = @(block) dct2(block.data);
A = blockproc(I,[8 8],f);</pre><pre>% Compute DCT coefficient variances and decide
% which to keep.
B = im2col(A,[8 8],'distinct')';
vars = var(B);
[~,idx] = sort(vars,'descend');
keep = idx(1:n);</pre><pre>% Zero out the DCT coefficients we are not keeping.
B2 = zeros(size(B));
B2(:,keep) = B(:,keep);</pre><pre>% Reconstruct image using 8-by-8 block inverse
% DCTs.
C = col2im(B2',[8 8],size(I),'distinct');
finv = @(block) idct2(block.data);
I2 = blockproc(C,[8 8],finv);
end</pre><p>I already have an <tt>update</tt> method in my class, so I can add code to that method that will compute the reconstructed image and error image. Here's the revised <tt>update</tt> method:</p><pre>function update(app)
    recon_image = reconstructImage(app.OriginalImage, ...
        app.NumDCTCoefficients);</pre><pre>    diff_image = imabsdiff(app.OriginalImage, recon_image);</pre><pre>    imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);
    title(app.OriginalImageAxes,'Original Image');</pre><pre>    imshow(recon_image,'Parent',app.ReconstructedImageAxes);
    title(app.ReconstructedImageAxes,'Reconstructed Image');</pre><pre>    imshow(diff_image,[],'Parent',app.ErrorImageAxes);
    title(app.ErrorImageAxes,'Error Image');</pre><pre>    imshow(zeros(size(app.OriginalImage)),'Parent',app.MaskAxes);
    title(app.MaskAxes,'DCT Coefficient Mask');
    drawnow;
end</pre><p>Although I don't have all the interactive behavior wired up yet, and don't have the DCT coefficient mask visualization done yet, the app runs and looks a bit more finished than it did before. It now shows the results for reconstructing the image from 3 DCT coefficients per block.</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dct-compression-example-v3.png" alt=""> </p><p>I think it'll take just one more post to finish making the rest of this app work.</p>
<div><ul><li><a href="http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/">Revisiting dctdemo - part 1</a></li><li><a href="http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/">Revisiting dctdemo - part 2</a></li><li><a href="http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/">Revisiting dctdemo - part 3</a></li><li><a href="http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/">Revisiting dctdemo - part 4</a></li></ul></div>
<script language="JavaScript"> <!-- 
    function grabCode_03724e04a81d4ac29734fd49392c5159() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='03724e04a81d4ac29734fd49392c5159 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 03724e04a81d4ac29734fd49392c5159';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_03724e04a81d4ac29734fd49392c5159()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2013a<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2013a<br /></p></div><!--
03724e04a81d4ac29734fd49392c5159 ##### SOURCE BEGIN #####
%%
% This is the third part of my plan to rewrite an Image Processing Toolbox
% example from 20 years ago using more modern MATLAB language features. I
% got the idea from Dave Garrison's 
% <http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html 
% recent article> on writing MATLAB apps.
%
% Here's the old app I'm trying to reinvent:
%
% <<http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png>>
%
% And here's what I had working the last time:
%
% <<http://blogs.mathworks.com/images/steve/2013/dct-compression-v2.png>>
%
% The code isn't doing any actual DCT computations yet. The idea is to
% compute 8-by-8 block DCTs, zero out the least significant DCT
% coefficients of each block, and then reconstruct the image by computing
% the inverse DCT of each 8-by-8 block.
%
% Let me show how this will work on the sample image I'm using for the app:

pout = imread('pout.tif');
pout2 = pout(1:240,:);
I = im2double(adapthisteq(pout2));
imshow(I)

%%
% First, use |blockproc| to compute the 8-by-8 2-D DCTs.

f = @(block) dct2(block.data);
A = blockproc(I,[8 8],f);
imshow(A,[])
title('DCT coefficients')

%%
% Second, I want to compute the variances of each of the 64 coefficients.
% That is, compute the variance of the (1,1) DCT coefficients from each
% block, the variance of the (1,2) DCT coefficients from each block, and so
% on. I'll use the computed variances to determine which DCT coefficients
% to keep and which to zero out. To do this, I'll rearrange the elements
% from the previous step so that the corresponding DCT coefficients are
% together in the columns of a 64-column matrix.

B = im2col(A,[8 8],'distinct')';
vars = var(B);
plot(vars)
title('Variances of the 64 DCT coefficients')

%%
% Next, suppose we want to keep the 3 block DCT coefficients with the
% highest variances. I'll use |sort| to figure out which ones to keep.

[~,idx] = sort(vars,'descend');
keep = idx(1:3)

%%
% For an 8-by-8 block of DCT coefficients, index values 1, 9, and 2
% correspond to the upper-left DCT coefficient and the two coefficients
% just the right and down from it. Let's keep just those coefficients.

B2 = zeros(size(B));
B2(:,keep) = B(:,keep);

%%
% Now I'll rearrange the columns back into blocks and reconstruct the image
% by computing the inverse DCT of each block.

C = col2im(B2',[8 8],size(I),'distinct');
finv = @(block) idct2(block.data);
D = blockproc(C,[8 8],finv);
imshow(D)
title('Image reconstructed from 3 DCT coefficients per block')

%%
% This algorithm code into a local function to go at the
% bottom of my app code file, like this:
%
%  function I2 = reconstructImage(I,n)
%  % Reconstruct the image from n of the DCT coefficients in each 8-by-8
%  % block. Select the n coefficients with the largest variance across the
%  % image.
%  
%  % Compute 8-by-8 block DCTs.
%  f = @(block) dct2(block.data);
%  A = blockproc(I,[8 8],f);
%  
%  % Compute DCT coefficient variances and decide
%  % which to keep.
%  B = im2col(A,[8 8],'distinct')';
%  vars = var(B);
%  [~,idx] = sort(vars,'descend');
%  keep = idx(1:n);
%  
%  % Zero out the DCT coefficients we are not keeping.
%  B2 = zeros(size(B));
%  B2(:,keep) = B(:,keep);
%  
%  % Reconstruct image using 8-by-8 block inverse
%  % DCTs.
%  C = col2im(B2',[8 8],size(I),'distinct');
%  finv = @(block) idct2(block.data);
%  I2 = blockproc(C,[8 8],finv);
%  end
%
% I already have an |update| method in my class, so I can add code to that
% method that will compute the reconstructed image and error image. Here's
% the revised |update| method:
%
%  function update(app)
%      recon_image = reconstructImage(app.OriginalImage, ...
%          app.NumDCTCoefficients);
%      
%      diff_image = imabsdiff(app.OriginalImage, recon_image);
%      
%      imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);
%      title(app.OriginalImageAxes,'Original Image');
%      
%      imshow(recon_image,'Parent',app.ReconstructedImageAxes);
%      title(app.ReconstructedImageAxes,'Reconstructed Image');
%      
%      imshow(diff_image,[],'Parent',app.ErrorImageAxes);
%      title(app.ErrorImageAxes,'Error Image');
%      
%      imshow(zeros(size(app.OriginalImage)),'Parent',app.MaskAxes);
%      title(app.MaskAxes,'DCT Coefficient Mask');
%      drawnow;
%  end
%
% Although I don't have all the interactive behavior wired up yet, and
% don't have the DCT coefficient mask visualization done yet, the app runs
% and looks a bit more finished than it did before. It now shows the
% results for reconstructing the image from 3 DCT coefficients per block.
%
% <<http://blogs.mathworks.com/images/steve/2013/dct-compression-example-v3.png>>
%
% I think it'll take just one more post to finish making the rest of this
% app work.

##### SOURCE END ##### 03724e04a81d4ac29734fd49392c5159
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/c0gCy6KbXzw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/</feedburner:origLink></item>
		<item>
		<title>MATLAB software testing tools – old and new (R2013a!)</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/6qwsaNJpkOE/</link>
		<comments>http://blogs.mathworks.com/steve/2013/03/12/matlab-software-testing-tools-old-and-new-r2013a/#comments</comments>
		<pubDate>Tue, 12 Mar 2013 18:45:14 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=805</guid>
		<description><![CDATA[R2013a, the latest semi-annual MathWorks product release, just went live. One of the significant new capabilities in the MATLAB release is a new unit test framework (overview video, documentation). I am very happy to see this!Long-time blog readers might be wondering, though, what about MATLAB xUnit? This is a unit test framework that I created [...]]]></description>
				<content:encoded><![CDATA[
<div class="content"><p>R2013a, the latest <a href="http://www.mathworks.com/products/new_products/release_model.html">semi-annual MathWorks product release</a>, just went live. One of the significant new capabilities in the MATLAB release is a new unit test framework (<a href="http://www.mathworks.com/videos/matlab-unit-testing-framework-74975.html">overview video</a>, <a href="http://www.mathworks.com/help/matlab/matlab-unit-test-framework.html">documentation</a>). I am very happy to see this!</p><p>Long-time blog readers might be wondering, though, what about MATLAB xUnit? This is a unit test framework that I created and put on the <a href="http://www.mathworks.com/matlabcentral/fileexchange/22846-matlab-xunit-test-framework">File Exchange</a>. I first wrote about it in this space in <a href="http://blogs.mathworks.com/steve/2009/02/03/mtest-a-unit-test-harness-for-matlab-code/">2009</a>. It is my second most popular File Exchange contribution (over 200 downloads in the last 30 days).</p><p>Today I want to recap how MATLAB xUnit came to be, explain what will probably happen to it, and convince its users to give the new "official" unit test framework in R2013a a try.</p><p>I learned to write unit tests when I came to MathWorks in 1993 as a new software developer. I've used several generations of test frameworks created for internal use here. Until recently, our internal testing machinery was tightly coupled to the entire system we used to build, test, and release our products, and so it was impractical to use it for small projects. This became an issue for me sometime around 2002-2003, as I was working on the first edition of <a href="http://imageprocessingplace.com/DIPUM-2E/dipum2e_main_page.htm"><i>Digital Image Processing Using MATLAB</i></a>. As the "software guy" among the three coauthors, I was responsible for overseeing the MATLAB functions in the book, including making sure that everything was working OK. So I wrote a simple test harness that exercised the book's examples and some of the functions.</p><p>Later, the MATLAB R2008a release included the new generation of object-oriented language features. I was interested in learning more about it. Coincidentally, I had just read Kent Beck's <i>Test-Driven Development</i>, which included a case study on using test-driven development methods to create an xUnit-style test harness. I decided that would be an excellent project with which to learn about test-driven development as well as the R2008a MATLAB language changes. (With the wisdom of hindsight, I have to say here that I don't actually recommend learning test-driven development by using test-driven development to develop a test harness. It hurt my brain too much.)</p><p>Anyway, sometime in the spring on 2008 I had something pretty basic working. At about that time, <a href="http://third-bit.com/">Greg Wilson</a> (original creator of <a href="http://software-carpentry.org/index.html">Software Carpentry</a>) visited MathWorks to give a talk about his edited book, <i>Beautiful Code</i>. I met Greg then, and we talked about the needs of MATLAB scientific users. Greg encouraged me to turn my fledgling tool into something real. He also invited me to write up something for the IEEE magazine, <i>Computing in Science and Engineering</i>. That became the article <a href="http://blogs.mathworks.com/images/steve/2010/Automated%20Software%20Testing%20for%20MATLAB%20(2009).pdf">"Automated Software Testing for MATLAB"</a>, published in the November/December 2009 issue.</p><p>The MATLAB xUnit package raised the visibility of unit testing tools in MATLAB, and its popularity helped make the case for putting something like it in MATLAB. At the same time, our testing tools team was looking to modernize our testing infrastructure. They wanted to take advantage of the latest test framework design principles, and they wanted to decouple the testing machinery from the rest of our complex systems for building and releasing products. So an idea was born: let's make a test framework that can stand on its own, that can test our own software, that can test customer code, and that we can ship in MATLAB!</p><p>And now, here it finally is!</p><p>Here are a few examples that I've taken from the documentation to illustrate. The first example shows how to write a couple of tests for a hypothetical function called <tt>quadraticSolver</tt>.</p><pre>classdef SolverTest &lt; matlab.unittest.TestCase
    % SolverTest tests solutions to the quadratic equation
    % a*x^2 + b*x + c = 0</pre><pre>    methods (Test)
        function testRealSolution(testCase)
            actSolution = quadraticSolver(1,-3,2);
            expSolution = [2,1];
            testCase.verifyEqual(actSolution,expSolution);
        end
        function testImaginarySolution(testCase)
            actSolution = quadraticSolver(1,2,10);
            expSolution = [-1+3i, -1-3i];
            testCase.verifyEqual(actSolution,expSolution);
        end
    end</pre><pre>end</pre><p>If you need to define setup and teardown methods for your test cases, here's how you do it. (I've just shown the relevant portion of the entire test file.)</p><pre>properties
    TestFigure
end</pre><pre>methods(TestMethodSetup)
    function createFigure(testCase)
        %comment
        testCase.TestFigure = figure;
    end
end</pre><pre>methods(TestMethodTeardown)
    function closeFigure(testCase)
        close(testCase.TestFigure);
    end
end</pre><p>Someone asked me just this week about enhancing MATLAB xUnit to provide for setup and teardown methods that get executed just once for all the methods in a test file, instead of being executed once for every individual test method. MATLAB xUnit does not have this capability, but the new unit test framework in R2013a does. A class-level setup method is identified by using the <tt>TestClassSetup</tt> method attribute, like this:</p><pre>methods (TestClassSetup)
    function doSomethingBeforeAllTestMethodsAreExecuted(testCase)
        disp('Hi, Mom!')
    end
end</pre><p>There are lots of new capabilities in this framework. A little birdie told me that more information about <tt>matlab.unittest</tt> may appear pretty soon in <a href="http://blogs.mathworks.com/loren">Loren's blog</a>. For now, though, I'd like to point you to the <a href="http://www.mathworks.com/videos/matlab-unit-testing-framework-74975.html">overview video</a> and to the <a href="http://www.mathworks.com/help/matlab/matlab-unit-test-framework.html">documentation</a>.</p><p>That brings me back to <a href="http://www.mathworks.com/matlabcentral/fileexchange/22846-matlab-xunit-test-framework">MATLAB xUnit</a> and its fate. Well, this little package is entering its "retirement phase." I imagine it will remain on the File Exchange for quite a while because it can take a long time for the user community to adopt a new release, and also because there's a lot of customer-written code out there that uses it. However, I do not plan to work on it anymore. Our testing tools team is an excellent group of engineers, and they can move matlab.unittest forward better and faster than I could ever do with my little side project.</p><p>So, if you're interested in unit testing and you get your hands on MATLAB R2013a, please give it a try.</p><script language="JavaScript"> <!-- 
    function grabCode_6ee60e2edacb49718a9915959d2debfe() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='6ee60e2edacb49718a9915959d2debfe ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 6ee60e2edacb49718a9915959d2debfe';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_6ee60e2edacb49718a9915959d2debfe()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2012b<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2012b<br /></p></div><!--
6ee60e2edacb49718a9915959d2debfe ##### SOURCE BEGIN #####
%%
% R2013a, the latest
% <http://www.mathworks.com/products/new_products/release_model.html
% semi-annual MathWorks product release>, just went live. One of the
% significant new capabilities in the MATLAB release is a new unit test
% framework
% (<http://www.mathworks.com/videos/matlab-unit-testing-framework-74975.html
% overview video>,
% <http://www.mathworks.com/help/matlab/matlab-unit-test-framework.html
% documentation>). I am very happy to see this!
%
% Long-time blog readers might be wondering, though, what about MATLAB
% xUnit? This is a unit test framework that I created and put on the
% <http://www.mathworks.com/matlabcentral/fileexchange/22846-matlab-xunit-test-framework
% File Exchange>. I first wrote about it in this space in
% <http://blogs.mathworks.com/steve/2009/02/03/mtest-a-unit-test-harness-for-matlab-code/
% 2009>. It is my second most popular File Exchange contribution (over 200
% downloads in the last 30 days).
%
% Today I want to recap how MATLAB xUnit came to be, explain what will
% probably happen to it, and convince its users to give the new "official"
% unit test framework in R2013a a try.
%
% I learned to write unit tests when I came to MathWorks in 1993 as a new
% software developer. I've used several generations of test frameworks
% created for internal use here. Until recently, our internal testing
% machinery was tightly coupled to the entire system we used to build,
% test, and release our products, and so it was impractical to use it for
% small projects. This became an issue for me sometime around 2002-2003, as
% I was working on the first edition of
% <http://imageprocessingplace.com/DIPUM-2E/dipum2e_main_page.htm _Digital
% Image Processing Using MATLAB_>. As the "software guy" among the three
% coauthors, I was responsible for overseeing the MATLAB functions in the
% book, including making sure that everything was working OK. So I wrote a
% simple test harness that exercised the book's examples and some of the
% functions.
%
% Later, the MATLAB R2008a release included the new generation of
% object-oriented language features. I was interested in learning more
% about it. Coincidentally, I had just read Kent Beck's _Test-Driven
% Development_, which included a case study on using test-driven development
% methods to create an xUnit-style test harness. I decided that would be
% an excellent project with which to learn about test-driven development as
% well as the R2008a MATLAB language changes. (With the wisdom of
% hindsight, I have to say here that I don't actually recommend learning
% test-driven development by using test-driven development to develop a
% test harness. It hurt my brain too much.)
%
% Anyway, sometime in the spring on 2008 I had something pretty basic
% working. At about that time, <http://third-bit.com/ Greg Wilson>
% (original creator of <http://software-carpentry.org/index.html Software
% Carpentry>) visited MathWorks to give a talk about his edited book,
% _Beautiful Code_. I met Greg then, and we talked about the needs of
% MATLAB scientific users. Greg encouraged me to turn my fledgling tool
% into something real. He also invited me to write up something for the
% IEEE magazine, _Computing in Science and Engineering_. That became the
% article
% <http://blogs.mathworks.com/images/steve/2010/Automated%20Software%20Testing%20for%20MATLAB%20(2009).pdf
% "Automated Software Testing for MATLAB">, published in the
% November/December 2009 issue.
%
% The MATLAB xUnit package raised the visibility of unit testing tools in
% MATLAB, and its popularity helped make the case for putting something
% like it in MATLAB. At the same time, our testing tools team was looking
% to modernize our testing infrastructure. They wanted to take advantage of
% the latest test framework design principles, and they wanted to decouple
% the testing machinery from the rest of our complex systems for building
% and releasing products. So an idea was born: let's make a test framework
% that can stand on its own, that can test our own software, that can test
% customer code, and that we can ship in MATLAB!
%
% And now, here it finally is!
%
% Here are a few examples that I've taken from the documentation to
% illustrate. The first example shows how to write a couple of tests for a
% hypothetical function called |quadraticSolver|.
%
%  classdef SolverTest < matlab.unittest.TestCase
%      % SolverTest tests solutions to the quadratic equation
%      % a*x^2 + b*x + c = 0
%      
%      methods (Test)
%          function testRealSolution(testCase)
%              actSolution = quadraticSolver(1,-3,2);
%              expSolution = [2,1];
%              testCase.verifyEqual(actSolution,expSolution);
%          end
%          function testImaginarySolution(testCase)
%              actSolution = quadraticSolver(1,2,10);
%              expSolution = [-1+3i, -1-3i];
%              testCase.verifyEqual(actSolution,expSolution);
%          end
%      end
%      
%  end
%
% If you need to define setup and teardown methods for your test cases,
% here's how you do it. (I've just shown the relevant portion of the entire
% test file.)
%
%  properties
%      TestFigure
%  end
%  
%  methods(TestMethodSetup)
%      function createFigure(testCase)
%          %comment
%          testCase.TestFigure = figure;
%      end
%  end
%  
%  methods(TestMethodTeardown)
%      function closeFigure(testCase)
%          close(testCase.TestFigure);
%      end
%  end
%
% Someone asked me just this week about enhancing MATLAB xUnit to provide
% for setup and teardown methods that get executed just once for all the
% methods in a test file, instead of being executed once for every
% individual test method. MATLAB xUnit does not have this capability, but
% the new unit test framework in R2013a does. A class-level setup method is
% identified by using the |TestClassSetup| method attribute, like this:
%
%  methods (TestClassSetup)
%      function doSomethingBeforeAllTestMethodsAreExecuted(testCase)
%          disp('Hi, Mom!')
%      end
%  end
%
% There are lots of new capabilities in this framework. A little birdie
% told me that more information about |matlab.unittest| may appear pretty
% soon in <http://blogs.mathworks.com/loren Loren's blog>. For now, though,
% I'd like to point you to the
% <http://www.mathworks.com/videos/matlab-unit-testing-framework-74975.html
% overview video> and to the
% <http://www.mathworks.com/help/matlab/matlab-unit-test-framework.html
% documentation>.
%
% That brings me back to
% <http://www.mathworks.com/matlabcentral/fileexchange/22846-matlab-xunit-test-framework
% MATLAB xUnit> and its fate. Well, this little package is entering its
% "retirement phase." I imagine it will remain on the File Exchange for
% quite a while because it can take a long time for the user community to
% adopt a new release, and also because there's a lot of customer-written
% code out there that uses it. However, I do not plan to work on it
% anymore. Our testing tools team is an excellent group of engineers, and
% they can move matlab.unittest forward better and faster than I could ever
% do with my little side project.
%
% So, if you're interested in unit testing and you get your hands on MATLAB
% R2013a, please give it a try.

##### SOURCE END ##### 6ee60e2edacb49718a9915959d2debfe
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/6qwsaNJpkOE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/03/12/matlab-software-testing-tools-old-and-new-r2013a/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/03/12/matlab-software-testing-tools-old-and-new-r2013a/</feedburner:origLink></item>
		<item>
		<title>Revisiting dctdemo – part 2</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/-yRD2wr_FOs/</link>
		<comments>http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/#comments</comments>
		<pubDate>Thu, 21 Feb 2013 22:15:45 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=766</guid>
		<description><![CDATA[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.Recall the old app I'm trying to reinvent: 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 [...]]]></description>
				<content:encoded><![CDATA[
<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 vspace="5" hspace="5" src="http://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 vspace="5" hspace="5" src="http://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
</pre><pre class="codeoutput">
app = 

  dctCompressionExample_v2 handle

  Properties:
         OriginalImage: [240x240 double]
    ReconstructedImage: []
            ErrorImage: []
    DCTCoefficientMask: []
    NumDCTCoefficients: 10


</pre><img vspace="5" hspace="5" src="http://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)
        OriginalImage
        ReconstructedImage
        ErrorImage
        DCTCoefficientMask
    end</pre><pre>    properties
        NumDCTCoefficients = 10
    end</pre><pre>    properties (Access = private)
        Slider
        OriginalImageAxes
        ReconstructedImageAxes
        ErrorImageAxes
        MaskAxes
    end</pre><pre>    methods
        function this_app = dctCompressionExample_v2
            this_app.OriginalImage = initialImage;
            layoutApp(this_app);
            update(this_app);
        end</pre><pre>        function layoutApp(app)
            f = figure;
            app.OriginalImageAxes = axes('Parent',f, ...
                'Position',[0.12 0.56 0.28 0.28]);
            app.ReconstructedImageAxes = axes('Parent',f, ...
                'Position',[0.60 0.56 0.28 0.28]);
            app.MaskAxes = axes('Parent',f, ...
                'Position',[0.12 0.16 0.28 0.28]);
            app.ErrorImageAxes = axes('Parent',f, ...
                'Position',[0.60 0.16 0.28 0.28]);
            app.Slider = uicontrol('Style','slider', ...
                'Value',app.NumDCTCoefficients/64, ...
                'Units','normalized', ...
                'Position',[0.12 0.08 0.28 0.04], ...
                'Callback',@(~,~,~) app.reactToSliderChange);</pre><pre>        end</pre><pre>        function reactToSliderChange(app)
            v = get(app.Slider,'Value');
            app.NumDCTCoefficients = round(64*v);
            update(app);
        end</pre><pre>        function update(app)
            imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);
            title(app.OriginalImageAxes,'Original Image');</pre><pre>            imshow(app.OriginalImage,'Parent',app.ReconstructedImageAxes);
            title(app.ReconstructedImageAxes,'Reconstructed Image');</pre><pre>            imshow(zeros(size(app.OriginalImage)),'Parent',app.ErrorImageAxes);
            title(app.ErrorImageAxes,'Error Image');</pre><pre>            imshow(zeros(size(app.OriginalImage)),'Parent',app.MaskAxes);
            title(app.MaskAxes,'DCT Coefficient Mask');
            drawnow;
        end
    end</pre><pre>end</pre><pre>function I = initialImage
pout = imread('pout.tif');
pout2 = pout(1:240,:);
I = im2double(adapthisteq(pout2));
end</pre><p>At this point I'll remind you of Dave Garrison's <a href="http://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
            this_app.OriginalImage = initialImage;
            layoutApp(this_app);
            update(this_app);
        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
pout = imread('pout.tif');
pout2 = pout(1:240,:);
I = im2double(adapthisteq(pout2));
end</pre><p>Then there's the properties block.</p><pre>    properties (SetAccess = private)
        OriginalImage
        ReconstructedImage
        ErrorImage
        DCTCoefficientMask
    end</pre><pre>    properties
        NumDCTCoefficients = 10
    end</pre><pre>    properties (Access = private)
        Slider
        OriginalImageAxes
        ReconstructedImageAxes
        ErrorImageAxes
        MaskAxes
    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', ...
                'Value',app.NumDCTCoefficients/64, ...
                'Units','normalized', ...
                'Position',[0.12 0.08 0.28 0.04], ...
                '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)
            v = get(app.Slider,'Value');
            app.NumDCTCoefficients = round(64*v);
            update(app);
        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>
<div><ul><li><a href="http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/">Revisiting dctdemo - part 1</a></li><li><a href="http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/">Revisiting dctdemo - part 2</a></li><li><a href="http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/">Revisiting dctdemo - part 3</a></li><li><a href="http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/">Revisiting dctdemo - part 4</a></li></ul></div>
<script language="JavaScript"> <!-- 
    function grabCode_ae0e4adbb7c2495998ab1c458bb46972() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='ae0e4adbb7c2495998ab1c458bb46972 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' ae0e4adbb7c2495998ab1c458bb46972';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </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 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2012b<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2012b<br /></p></div><!--
ae0e4adbb7c2495998ab1c458bb46972 ##### SOURCE BEGIN #####
%%
% 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.
%
% Recall the old app I'm trying to reinvent:
%
% <<http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png>>
%
% 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.
%
% Here's my first attempt at sketching what I'd like to make this time
% around.
%
% <<http://blogs.mathworks.com/images/steve/2013/dct-compression-sketch.jpg>>
%
% 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.
%
% Here's what happens when I call the app class, which I've called (for
% now) |dctCompressionExample_v2|.

app = dctCompressionExample_v2

%%
% You can see I got some output in the Command Window, and I also got a
% new figure on the screen.
% 
% Here's the code so far.
%
%  classdef dctCompressionExample_v2 < handle
%      
%      properties (SetAccess = private)
%          OriginalImage
%          ReconstructedImage
%          ErrorImage
%          DCTCoefficientMask
%      end
%      
%      properties
%          NumDCTCoefficients = 10
%      end
%      
%      properties (Access = private)
%          Slider
%          OriginalImageAxes
%          ReconstructedImageAxes
%          ErrorImageAxes
%          MaskAxes
%      end
%      
%      methods
%          function this_app = dctCompressionExample_v2
%              this_app.OriginalImage = initialImage;
%              layoutApp(this_app);
%              update(this_app);
%          end
%          
%          function layoutApp(app)
%              f = figure;
%              app.OriginalImageAxes = axes('Parent',f, ...
%                  'Position',[0.12 0.56 0.28 0.28]);
%              app.ReconstructedImageAxes = axes('Parent',f, ...
%                  'Position',[0.60 0.56 0.28 0.28]);
%              app.MaskAxes = axes('Parent',f, ...
%                  'Position',[0.12 0.16 0.28 0.28]);
%              app.ErrorImageAxes = axes('Parent',f, ...
%                  'Position',[0.60 0.16 0.28 0.28]);
%              app.Slider = uicontrol('Style','slider', ...
%                  'Value',app.NumDCTCoefficients/64, ...
%                  'Units','normalized', ...
%                  'Position',[0.12 0.08 0.28 0.04], ...
%                  'Callback',@(~,~,~) app.reactToSliderChange);
%              
%          end
%          
%          function reactToSliderChange(app)
%              v = get(app.Slider,'Value');
%              app.NumDCTCoefficients = round(64*v);
%              update(app);
%          end
%          
%          function update(app)
%              imshow(app.OriginalImage,'Parent',app.OriginalImageAxes);
%              title(app.OriginalImageAxes,'Original Image');
%              
%              imshow(app.OriginalImage,'Parent',app.ReconstructedImageAxes);
%              title(app.ReconstructedImageAxes,'Reconstructed Image');
%              
%              imshow(zeros(size(app.OriginalImage)),'Parent',app.ErrorImageAxes);
%              title(app.ErrorImageAxes,'Error Image');
%              
%              imshow(zeros(size(app.OriginalImage)),'Parent',app.MaskAxes);
%              title(app.MaskAxes,'DCT Coefficient Mask');
%              drawnow;
%          end
%      end
%      
%  end
%  
%  function I = initialImage
%  pout = imread('pout.tif');
%  pout2 = pout(1:240,:);
%  I = im2double(adapthisteq(pout2));
%  end
%
% At this point I'll remind you of Dave Garrison's
% <http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html
% article> 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.
%
% Here's the function that runs when you launch the app.
%
%          function this_app = dctCompressionExample_v2
%              this_app.OriginalImage = initialImage;
%              layoutApp(this_app);
%              update(this_app);
%          end
%
% |initialImage| 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 |adapthisteq| because the original image has low
% contrast.)
%
%  function I = initialImage
%  pout = imread('pout.tif');
%  pout2 = pout(1:240,:);
%  I = im2double(adapthisteq(pout2));
%  end
%
% Then there's the properties block. 
%
%      properties (SetAccess = private)
%          OriginalImage
%          ReconstructedImage
%          ErrorImage
%          DCTCoefficientMask
%      end
%      
%      properties
%          NumDCTCoefficients = 10
%      end
%      
%      properties (Access = private)
%          Slider
%          OriginalImageAxes
%          ReconstructedImageAxes
%          ErrorImageAxes
%          MaskAxes
%      end
%
% Some of the properties, such as |OriginalImage|, I want to make
% accessible but read-only. Some of them, such as |OriginalImageAxes|, are
% private because they are only needed by the guts of the app. Notice that
% one of them, |NumDCTCoefficients|, is both readable *and* 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.
% 
% I would like to make it so that the |NumDCTCoefficients| property changes
% when you drag the slider. Here's how to accomplish that:
%
%              app.Slider = uicontrol('Style','slider', ...
%                  'Value',app.NumDCTCoefficients/64, ...
%                  'Units','normalized', ...
%                  'Position',[0.12 0.08 0.28 0.04], ...
%                  'Callback',@(~,~,~) app.reactToSliderChange);
%
% Setting the |'Callback'| property of the slider like this causes the
% app's function |reactToSliderChange| to get called whenever the slider is
% dragged. Here's what |reactToSliderChange| does:
%
%          function reactToSliderChange(app)
%              v = get(app.Slider,'Value');
%              app.NumDCTCoefficients = round(64*v);
%              update(app);
%          end
%
% Now we're starting to get a little interactivity going in our app.
%
% 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.
##### SOURCE END ##### ae0e4adbb7c2495998ab1c458bb46972
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/-yRD2wr_FOs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/</feedburner:origLink></item>
		<item>
		<title>Revisiting dctdemo – Part 1</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/_EiKStN3EpU/</link>
		<comments>http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/#comments</comments>
		<pubDate>Fri, 08 Feb 2013 15:19:06 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=761</guid>
		<description><![CDATA[Last month, Dave Garrison wrote a nice article on the MathWorks web site about coding an app (or GUI) by defining a class.Curiously, this article made me think of a day back in September 1993. I arrived at MathWorks on that day to interview for a job as an image processing software developer. Sometime in [...]]]></description>
				<content:encoded><![CDATA[<div class="content"><p>Last month, Dave Garrison wrote a <a href="http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html">nice article</a> on the MathWorks web site about coding an app (or GUI) by defining a class.</p><p>Curiously, this article made me think of a day back in September 1993. I arrived at MathWorks on that day to interview for a job as an image processing software developer. Sometime in the afternoon I found myself in an office with the two developers of version 1.0 of the Image Processing Toolbox. (One of those developers, Loren Shure, was the first employee hired by the MathWorks founders. You can find her over at <a href="http://blogs.mathworks.com/loren">Loren on the Art of MATLAB</a>.)</p><p>Anyway, the Image Processing Toolbox was about to ship, and the developers were trying to think of some demo ideas. I joined in a brainstorming session in front of a whiteboard. One of my ideas that day became the product demo called <tt>dctdemo</tt>. Here is a screen shot.</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png" alt=""> </p><p>(That's a picture of Loren, by the way.)</p><p>Prompted by Dave's article, I thought it might be a good time to revisit this oldie-but-goodie demo. It was originally written using MATLAB 4, and the programming techniques available at that time for doing this sort of thing were relatively crude. My plan is to take a fresh look at this demo and reimplement it using the techniques described by Dave.</p><p>Here's a start:</p><pre class="language-matlab"><span class="keyword">classdef</span> dctCompressionDemo &lt; handle
</pre><pre class="language-matlab"><span class="keyword">end</span>
</pre><p>That's enough code to actually execute.</p><pre class="codeinput">dctCompressionDemo
</pre><pre class="codeoutput">
ans = 

  dctCompressionDemo handle with no properties.

</pre><p>And that's about all it does (for now). Next time we'll start filling in the details.</p>
<div><ul><li><a href="http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/">Revisiting dctdemo - part 1</a></li><li><a href="http://blogs.mathworks.com/steve/2013/02/21/revisiting-dctdemo-part-2/">Revisiting dctdemo - part 2</a></li><li><a href="http://blogs.mathworks.com/steve/2013/03/21/revisiting-dctdemo-part-3/">Revisiting dctdemo - part 3</a></li><li><a href="http://blogs.mathworks.com/steve/2013/04/12/revisiting-dctdemo-part-4/">Revisiting dctdemo - part 4</a></li></ul></div>
<script language="JavaScript"> <!-- 
    function grabCode_ac4a98d2dc6a4b8c94b3a679ec387ad6() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='ac4a98d2dc6a4b8c94b3a679ec387ad6 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' ac4a98d2dc6a4b8c94b3a679ec387ad6';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_ac4a98d2dc6a4b8c94b3a679ec387ad6()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2012b<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2012b<br /></p></div><!--
ac4a98d2dc6a4b8c94b3a679ec387ad6 ##### SOURCE BEGIN #####
%%
% Last month, Dave Garrison wrote a
% <http://www.mathworks.com/company/newsletters/articles/writing-apps-in-matlab.html
% nice article> on the MathWorks web site about coding an app (or GUI) by
% defining a class.
%
% Curiously, this article made me think of a day back in September 1993. I
% arrived at MathWorks on that day to interview for a job as an image
% processing software developer. Sometime in the afternoon I found myself
% in an office with the two developers of version 1.0 of the Image Processing
% Toolbox. (One of those developers, Loren Shure, was the first employee
% hired by the MathWorks founders. You can find her over at
% <http://blogs.mathworks.com/loren Loren on the Art of MATLAB>.)
%
% Anyway, the Image Processing Toolbox was about to ship, and the
% developers were trying to think of some demo ideas. I joined in a
% brainstorming session in front of a whiteboard. One of my ideas that
% day became the product demo called |dctdemo|. Here is a screen shot.
%
% <<http://blogs.mathworks.com/images/steve/2013/dctdemo-screen-shot.png>>
%
% (That's a picture of Loren, by the way.)
%
% Prompted by Dave's article, I thought it might be a good time to revisit
% this oldie-but-goodie demo. It was originally written using MATLAB 4, and
% the programming techniques available at that time for doing this sort of
% thing were relatively crude. My plan is to take a fresh look at this demo
% and reimplement it using the techniques described by Dave.
%
% Here's a start:
%
%   classdef dctCompressionDemo < handle
%
%   end
%
% That's enough code to actually execute.

dctCompressionDemo

%%
% And that's about all it does (for now). Next time we'll start filling in
% the details.
##### SOURCE END ##### ac4a98d2dc6a4b8c94b3a679ec387ad6
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/_EiKStN3EpU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/02/08/revisiting-dctdemo-part-1/</feedburner:origLink></item>
		<item>
		<title>George Forsythe is inside the default MATLAB image</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/RcXYG0kN6v4/</link>
		<comments>http://blogs.mathworks.com/steve/2013/01/28/george-forsythe-is-inside-the-default-matlab-image/#comments</comments>
		<pubDate>Mon, 28 Jan 2013 21:13:36 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=754</guid>
		<description><![CDATA[A couple of weeks ago, Cleve wrote a post about George Forsythe, Cleve's "thesis advisor, colleague, and friend."In that post, Cleve showed some MATLAB code to load in and display a 1964 picture of the organizing committee of the Gatlinburg conferences on numerical algebra.load gatlin image(X) colormap(map) axis image axis off As Cleve mentioned, this [...]]]></description>
				<content:encoded><![CDATA[<div class="content"><p>A couple of weeks ago, <a href="http://blogs.mathworks.com/cleve">Cleve</a> wrote a <a href="http://blogs.mathworks.com/cleve/2013/01/07/george-forsythe/">post about George Forsythe</a>, Cleve's "thesis advisor, colleague, and friend."</p><p>In that post, Cleve showed some MATLAB code to load in and display a 1964 picture of the organizing committee of the Gatlinburg conferences on numerical algebra.</p><pre class="codeinput">load <span class="string">gatlin</span>
image(X)
colormap(map)
axis <span class="string">image</span>
axis <span class="string">off</span>
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/default_image_again_01.png" alt=""> <p>As Cleve mentioned, this picture is one of the very first images distributed with MATLAB. (I recall getting the first MATLAB version capable of image display sometime around 1990. It was very exciting!)</p><p>As it turns out, there is another interesting method in MATLAB to display this picture (or at least a cropped, low-resolution version of it):</p><pre class="codeinput">default_image = pow2(get(0,<span class="string">'DefaultImageCData'</span>),47);
numbits = 12 - 9 + 1;
b = bitshift(default_image,-9);
b = fix(b);
b = bitand(b,bitcmp(0,4));
b = b/max(b(:));

imshow(b,<span class="string">'InitialMagnification'</span>,200)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/default_image_again_02.png" alt=""> <p>Forsythe is on the right of the cropped version.</p><p>So, what's going on here? Well, it turns out that, if you call <tt>image</tt> with no input arguments (no data), an image with "default" pixel values gets displayed. Furthermore, that image has many images "hidden" within it. For the full story, see <a href="http://blogs.mathworks.com/steve/2006/10/17/the-story-behind-the-matlab-default-image/">"The Story Behind the Default MATLAB Image."</a></p><p>Cleve knew that I was working on this little hidden-image project in the mid-1990s, and I asked him for suggestions about images to include. He suggested this Gatlinburg Conference picture, as well as the 4-by-4 Durer magic square.</p><pre class="codeinput">c = bitshift(default_image,-23);
c = fix(c);
c = bitand(c,bitcmp(0,5));
c = c/max(c(:));

imshow(c,<span class="string">'InitialMagnification'</span>,200)
</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2013/default_image_again_03.png" alt=""> <p>Thanks for the suggestions, Cleve!</p><script language="JavaScript"> <!-- 
    function grabCode_2ff8e05cb7504dd9a3fd9f8ebee00ebb() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='2ff8e05cb7504dd9a3fd9f8ebee00ebb ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 2ff8e05cb7504dd9a3fd9f8ebee00ebb';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_2ff8e05cb7504dd9a3fd9f8ebee00ebb()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2012b<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2012b<br /></p></div><!--
2ff8e05cb7504dd9a3fd9f8ebee00ebb ##### SOURCE BEGIN #####
%%
% A couple of weeks ago, <http://blogs.mathworks.com/cleve Cleve> wrote a
% <http://blogs.mathworks.com/cleve/2013/01/07/george-forsythe/ post about
% George Forsythe>, Cleve's "thesis advisor, colleague, and friend."
%
% In that post, Cleve showed some MATLAB code to load in and display a
% 1964 picture of the organizing committee of the Gatlinburg conferences on
% numerical algebra.

load gatlin
image(X)
colormap(map)
axis image
axis off

%%
% As Cleve mentioned, this picture is one of the very first images
% distributed with MATLAB. (I recall getting the first MATLAB version
% capable of image display sometime around 1990. It was very exciting!)
%
% As it turns out, there is another interesting method in MATLAB to display
% this picture (or at least a cropped, low-resolution version of it):

default_image = pow2(get(0,'DefaultImageCData'),47);
numbits = 12 - 9 + 1;
b = bitshift(default_image,-9);
b = fix(b);
b = bitand(b,bitcmp(0,4));
b = b/max(b(:));

imshow(b,'InitialMagnification',200)

%%
% Forsythe is on the right of the cropped version.
%
% So, what's going on here? Well, it turns out that, if you call |image|
% with no input arguments (no data), an image with "default" pixel values
% gets displayed. Furthermore, that image has many images "hidden" within it.
% For the full story, see
% <http://blogs.mathworks.com/steve/2006/10/17/the-story-behind-the-matlab-default-image/
% "The Story Behind the Default MATLAB Image.">
%
% Cleve knew that I was working on this little hidden-image project in the
% mid-1990s, and I asked him for suggestions about images to include. He
% suggested this Gatlinburg Conference picture, as well as the 4-by-4 Durer
% magic square.

c = bitshift(default_image,-23);
c = fix(c);
c = bitand(c,bitcmp(0,5));
c = c/max(c(:));

imshow(c,'InitialMagnification',200)

%%
% Thanks for the suggestions, Cleve!
##### SOURCE END ##### 2ff8e05cb7504dd9a3fd9f8ebee00ebb
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/RcXYG0kN6v4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/01/28/george-forsythe-is-inside-the-default-matlab-image/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/01/28/george-forsythe-is-inside-the-default-matlab-image/</feedburner:origLink></item>
		<item>
		<title>Digital Image Processing Using MATLAB: Data Types</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/5B5cXP5arYA/</link>
		<comments>http://blogs.mathworks.com/steve/2013/01/15/data-types/#comments</comments>
		<pubDate>Tue, 15 Jan 2013 17:52:27 +0000</pubDate>
		<dc:creator>Steve Eddins</dc:creator>
				<category><![CDATA[DIPUM tutorials]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/?p=745</guid>
		<description><![CDATA[Today's post is part of an ongoing tutorial series on digital image processing using MATLAB. I'm covering topics in roughly the order used in the book Digital Image Processing Using MATLAB.When working with images in MATLAB, it is important to understand how different numeric data types can come into play.The most common numeric data type [...]]]></description>
				<content:encoded><![CDATA[<div class="content"><p><i>Today's post is part of an <a href="http://blogs.mathworks.com/steve/category/dipum-tutorials/">ongoing tutorial series on digital image processing using MATLAB</a>. I'm covering topics in roughly the order used in the book <a href="http://imageprocessingplace.com/DIPUM-2E/dipum2e_main_page.htm">Digital Image Processing Using MATLAB</a>.</i></p><p>When working with images in MATLAB, it is important to understand how different numeric data types can come into play.</p><p>The most common numeric data type in MATLAB is <tt>double</tt>, which stands for <i>double-precision floating point</i>. It's the representation of numbers that you get by default when you type numbers into MATLAB.</p><pre class="codeinput">a = [0.1 0.125 1.3]
</pre><pre class="codeoutput">
a =

    0.1000    0.1250    1.3000

</pre><pre class="codeinput">class(a)
</pre><pre class="codeoutput">
ans =

double

</pre><p>Double-precision floating-point numbers are intended to approximate the set of real numbers. To a reasonable degree, one can do arithmetic computations on these numbers using MATLAB (and the computational hardware on your CPU or GPU) and get the same results as "true arithmetic" (or "God's math," as I've heard Cleve say) on the real numbers.</p><p>Working with floating-point numbers is very useful for mathematical image processing algorithms (such as filtering, Fourier transforms, deblurring, color computations, and many others).</p><p>Prior to 1997, the <tt>double</tt> was the only kind of data type in MATLAB. Image processing customers complained about this because of the memory required for these kinds of numbers. A double-precision floating-point number requires 64 bits, whereas many people working with image data were used to using only 8 bits (or even just 1 bit in the case of binary images) to store each pixel value.</p><p>So with MATLAB 5 and Image Processing Toolbox 2 in 1997, we introduced support for a new data type, <tt>uint8</tt>, which is an abbreviation for <i>unsigned 8-bit integer</i>. This data requires just 8 bits to represent a number, but the representable set of numbers is limited to the integers from 0 to 255.</p><p>You can make one in MATLAB by calling the <tt>uint8</tt> function.</p><pre class="codeinput">b = uint8(5)
</pre><pre class="codeoutput">
b =

    5

</pre><pre class="codeinput">class(b)
</pre><pre class="codeoutput">
ans =

uint8

</pre><p>Also, you often see <tt>uint8</tt> numbers when you call the <tt>imread</tt> to read an image from a file. That's because image file formats often use 8 bits (prior to compression) to store each pixel value.</p><pre class="codeinput">rgb = imread(<span class="string">'peppers.png'</span>);
rgb(1:3,1:4,1)
</pre><pre class="codeoutput">
ans =

   62   63   63   65
   63   61   59   64
   65   63   63   66

</pre><pre class="codeinput">class(rgb)
</pre><pre class="codeoutput">
ans =

uint8

</pre><p>Almost immediately after MATLAB 5 and Image Processing Toolbox 2, we started hearing from customers who had scientific data stored using 16 bits for value, so 8 bits wasn't enough and 64 bits (for <tt>double</tt>) still seemed wasteful. So Image Processing Toolbox 2.2 in 1999 added support for <tt>uint16</tt> numbers (unsigned 16-bit integers).</p><p>But still that wasn't enough. The medical imaging community, it seemed, needed <b>signed</b> 16-bit numbers. And, said many, what about single-precision floating-point?</p><p>For Image Processing Toolbox 3 in 2001, we stopped adding data type support piecemeal and instead added support for all the data types in MATLAB at the time. Here is a summary of the entire set:</p><div><ul><li><tt>double</tt> - double-precision, floating-point numbers in the approximate range $\pm 10^{308}$ (8 bytes per number)</li><li><tt>single</tt> - single-precision, floating-point numbers with values in the approximate range $\pm 10^{38}$ (4 bytes per number)</li><li><tt>uint8</tt> - unsigned 8-bit integers in the range [0,255] (1 byte per number)</li><li><tt>uint16</tt> - unsigned 16-bit integers in the range [0,65535] (2 bytes per number)</li><li><tt>uint32</tt> - unsigned 32-bit integers in the range [0,4294967295] (4 bytes per number)</li><li><tt>int8</tt> - signed 8-bit integer in the range [-128,127] (1 byte per number)</li><li><tt>int16</tt> - signed 16-bit integer in the range [-32768,32767] (2 bytes per number)</li><li><tt>int32</tt> - signed 32-bit integer in the range [-2147483648,2147483647] (4 bytes per number)</li></ul></div><p>Support for the <tt>logical</tt> data type (the only values are 0 and 1, 1 byte per number) was added a few years later.</p><p>Two other data types have appeared since then, <tt>uint64</tt> and <tt>int64</tt>. Relatively little effort has been made to support these data types for image processing, for two reasons:</p><div><ul><li>We don't get any customer requests for it</li><li>There are hard-to-answer behavior questions caused by the fact that there are <tt>uint64</tt> and <tt>int64</tt> numbers that can't be exactly represented as <tt>double</tt>, and some Image Processing Toolbox functions have an implicit assumption that one can convert an integer number to a double-precision floating-point number and back again without losing information in the process. But, as it turns out, there are plenty of large unsigned 64-bit numbers that can't be represented exactly in double-precision floating-point:</li></ul></div><pre class="codeinput">c = uint64(184467440737095516)
</pre><pre class="codeoutput">
c =

   184467440737095516

</pre><pre class="codeinput">d = double(c)
</pre><pre class="codeoutput">
d =

   1.8447e+17

</pre><pre class="codeinput">e = uint64(d)
</pre><pre class="codeoutput">
e =

   184467440737095520

</pre><pre class="codeinput">e - c
</pre><pre class="codeoutput">
ans =

                    4

</pre><p>When I pursue this topic further next time, I'll talk more about data type conversions: the basic ones in MATLAB, plus the Image Processing Toolbox ones that handle additional details of data scaling.</p><p>For more information, see Section 2.5 of <a href="http://imageprocessingplace.com/DIPUM-2E/dipum2e_main_page.htm"> <i>Digital Image Processing Using MATLAB</i></a>.</p><p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2011/dipum-cover.png" alt=""> </p><script language="JavaScript"> <!-- 
    function grabCode_3a960eb541034f2c838285a05d0618bf() {
        // Remember the title so we can use it in the new page
        title = document.title;

        // Break up these strings so that their presence
        // in the Javascript doesn't mess up the search for
        // the MATLAB code.
        t1='3a960eb541034f2c838285a05d0618bf ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 3a960eb541034f2c838285a05d0618bf';
    
        b=document.getElementsByTagName('body')[0];
        i1=b.innerHTML.indexOf(t1)+t1.length;
        i2=b.innerHTML.indexOf(t2);
 
        code_string = b.innerHTML.substring(i1, i2);
        code_string = code_string.replace(/REPLACE_WITH_DASH_DASH/g,'--');

        // Use /x3C/g instead of the less-than character to avoid errors 
        // in the XML parser.
        // Use '\x26#60;' instead of '<' so that the XML parser
        // doesn't go ahead and substitute the less-than character. 
        code_string = code_string.replace(/\x3C/g, '\x26#60;');

        copyright = 'Copyright 2013 The MathWorks, Inc.';

        w = window.open();
        d = w.document;
        d.write('<pre>\n');
        d.write(code_string);

        // Add copyright line at the bottom if specified.
        if (copyright.length > 0) {
            d.writeln('');
            d.writeln('%%');
            if (copyright.length > 0) {
                d.writeln('% _' + copyright + '_');
            }
        }

        d.write('</pre>\n');

        d.title = title + ' (MATLAB code)';
        d.close();
    }   
     --> </script><p style="text-align: right; font-size: xx-small; font-weight:lighter;   font-style: italic; color: gray"><br /><a href="javascript:grabCode_3a960eb541034f2c838285a05d0618bf()"><span style="font-size: x-small;        font-style: italic;">Get 
      the MATLAB code <noscript>(requires JavaScript)</noscript></span></a><br /><br />
      Published with MATLAB&reg; R2012b<br /></p><p class="footer"><br />
      Published with MATLAB&reg; R2012b<br /></p></div><!--
3a960eb541034f2c838285a05d0618bf ##### SOURCE BEGIN #####
%% Images and data types
% _Today's post is part of an
% <http://blogs.mathworks.com/steve/category/dipum-tutorials/ ongoing
% tutorial series on digital image processing using MATLAB>. I'm covering
% topics in roughly the order used in the book
% <http://imageprocessingplace.com/DIPUM-2E/dipum2e_main_page.htm Digital
% Image Processing Using MATLAB>._
%
% When working with images in MATLAB, it is important to understand how
% different numeric data types can come into play.
%
% The most common numeric data type in MATLAB is |double|, which stands for
% _double-precision floating point_. It's the representation of numbers
% that you get by default when you type numbers into MATLAB.

a = [0.1 0.125 1.3]

%%
class(a)

%%
% Double-precision floating-point numbers are intended to approximate the
% set of real numbers. To a reasonable degree, one can do arithmetic
% computations on these numbers using MATLAB (and the computational
% hardward on your CPU or GPU) and get the same results as "true
% arithmetic" (or "God's math," as I've heard Cleve say) on the real
% numbers.
%
% Working with floating-point numbers is very useful for mathematical image
% processing algorithms (such as filtering, Fourier transforms, deblurring,
% color computations, and many others).
%
% Prior to 1997, the |double| was the only kind of data type in MATLAB.
% Image processing customers complained about this because of the memory
% required for these kinds of numbers. A double-precision floating-point
% number requires 64 bits, whereas many people working with image data were
% used to using only 8 bits (or even just 1 bit in the case of binary
% images) to store each pixel value.
%
% So with MATLAB 5 and Image Processing Toolbox 2 in 1997, we introduced
% support for a new data type, |uint8|, which is an abbreviation for
% _unsigned 8-bit integer_. This data requires just 8 bits to represent a
% number, but the representable set of numbers is limited to the integers
% from 0 to 255.
%
% You can make one in MATLAB by calling the |uint8| function.

b = uint8(5)

%%
class(b)

%%
% Also, you often see |uint8| numbers when you call the |imread| to read an
% image from a file. That's because image file formats often use 8 bits
% (prior to compression) to store each pixel value.

rgb = imread('peppers.png');
rgb(1:3,1:4,1)

%%
class(rgb)

%%
% Almost immediately after MATLAB 5 and Image Processing Toolbox 2, we
% started hearing from customers who had scientific data stored using 16
% bits for value, so 8 bits wasn't enough and 64 bits (for |double|) still
% seemed wasteful. So Image Processing Toolbox 2.2 in 1999 added support
% for |uint16| numbers (unsigned 16-bit integers).
%
% But still that wasn't enough. The medical imaging community, it seemed,
% needed *signed* 16-bit numbers. And, said many, what about
% single-precision floating-point?
%
% For Image Processing Toolbox 3 in 2001, we stopped adding data type
% support piecemeal and instead added support for all the data types
% in MATLAB at the time. Here is a summary of the entire set:
%
% * |double| - double-precision, floating-point numbers in the approximate
% range $\pm 10^{308}$ (8 bytes per number)
% * |single| - single-precision, floating-point numbers with values in the
% approximate range $\pm 10^{38}$ (4 bytes per number)
% * |uint8| - unsigned 8-bit integers in the range [0,255] (1 byte per
% number)
% * |uint16| - unsigned 16-bit integers in the range [0,65535] (2 bytes per
% number)
% * |uint32| - unsigned 32-bit integers in the range [0,4294967295] (4
% bytes per number)
% * |int8| - signed 8-bit integer in the range [-128,127] (1 byte per
% number)
% * |int16| - signed 16-bit integer in the range [-32768,32767] (2 bytes
% per number)
% * |int32| - signed 32-bit integer in the range [-2147483648,2147483647]
% (4 bytes per number)
%
% Support for the |logical| data type (the only values are 0 and 1, 1 byte
% per number) was added a few years later.
%
% Two other data types have appeared since then, |uint64| and |int64|.
% Relatively little effort has been made to support these data types for
% image processing, for two reasons:
%
% * We don't get any customer requests for it
% * There are hard-to-answer behavior questions caused by the fact that
% there are |uint64| and |int64| numbers that can't be exactly represented
% as |double|, and some Image Processing Toolbox functions have an implicit
% assumption that one can convert an integer number to a double-precision
% floating-point number and back again without losing information in the
% process. But, as it turns out, there are plenty of large unsigned 64-bit
% numbers that can't be represented exactly in double-precision
% floating-point:

c = uint64(184467440737095516)

%%

d = double(c)

%%

e = uint64(d)

%%

e - c

%%
% When I pursue this topic further next time, I'll talk more about data
% type conversions: the basic ones in MATLAB, plus the Image Processing
% Toolbox ones that handle additional details of data scaling.

%%
% For more information, see Section 2.5 of
% <http://imageprocessingplace.com/DIPUM-2E/dipum2e_main_page.htm
%  _Digital Image Processing Using MATLAB_>. 
%
% <<http://blogs.mathworks.com/images/steve/2011/dipum-cover.png>>
##### SOURCE END ##### 3a960eb541034f2c838285a05d0618bf
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/5B5cXP5arYA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2013/01/15/data-types/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2013/01/15/data-types/</feedburner:origLink></item>
	</channel>
</rss>
