<?xml version="1.0" encoding="UTF-8"?>
<!-- generator="wordpress/2.3.1" --><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: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 &lt;a href="http://www.mathworks.com/"&gt;The MathWorks&lt;/a&gt; and coauthored &lt;a href="http://www.mathworks.com/support/books/book5291.html?category=-1&amp;language=-1"&gt;Digital Image Processing Using MATLAB&lt;/a&gt;. He writes here about image processing concepts, algorithm implementations, and MATLAB.&lt;br&gt;&lt;br&gt;&lt;img&gt;</description>
	<pubDate>Fri, 20 Nov 2009 19:56:36 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.3.1</generator>
	<language>en</language>
			<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com" /><item>
		<title>Extracting dot locations from a graphic</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/G3rwjkJNQAM/</link>
		<comments>http://blogs.mathworks.com/steve/2009/11/20/extracting-dot-locations-from-a-graphic/#comments</comments>
		<pubDate>Fri, 20 Nov 2009 19:56:36 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/11/20/extracting-dot-locations-from-a-graphic/</guid>
		<description><![CDATA[
   I was looking at the image below on a web page recently and I decided to extract the locations of all the dots. I thought the procedure might make a nice little end-of-the-week
      how-to post.
   % Did you know that imread can read directly from [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p>I was looking at the image below on a <a href="http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/alpha.html">web page</a> recently and I decided to extract the locations of all the dots. I thought the procedure might make a nice little end-of-the-week
      how-to post.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)"><span style="color: #228B22">% Did you know that imread can read directly from a URL?</span>
url = <span style="color: #A020F0">'http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/example1.gif'</span>;
[X, map] = imread(url);
imshow(X, map)</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/dot_locations_01.png"> <p>First question to answer: What is the index of the color used for the dots? One easy way to go is to use <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/imtool.html"><tt>imtool</tt></a>.
   </p>
   <p>Here's a screenshot:</p>
   <p><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/imtool-screen-shot.png"> </p>
   <p>As you can see, when I placed the mouse pointer over the center of one of the dots, the pixel info display at the lower left
      showed that the index value was 1, and the corresponding colormap color was [1.00, 0.78, 0.00].
   </p>
   <p>Now that we know the index value, we can easily make a binary image of just the interior of the dots.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">bw = X == 1;
imshow(bw)</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/dot_locations_02.png"> <p>Now we can compute the centroids of the dots.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">s = regionprops(bw, <span style="color: #A020F0">'Centroid'</span>)</pre><pre style="font-style:oblique">
s = 

122x1 struct array with fields:
    Centroid

</pre><p>The line above is a new syntax for <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/regionprops.html"><tt>regionprops</tt></a> that we introduced earlier this year in R2009a.  Previously, you always had to compute a label matrix first using <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/bwlabel.html"><tt>bwlabel</tt></a> and then pass that label matrix to <tt>regionprops</tt>.  Now <tt>regionprops</tt> can do this computation directly on the binary image.  Since the label matrix is not computed, this new syntax uses less
      memory and usually runs faster than the old version.
   </p>
   <p>For those of you using an older version, do this instead:</p><pre> L = bwlabel(bw);
 s = regionprops(L, 'Centroid');</pre><p>To show the results, display the image and then superimpose the centroid locations.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">imshow(X, map)
hold <span style="color: #A020F0">on</span>
<span style="color: #0000FF">for</span> k = 1:numel(s)
    centroid_k = s(k).Centroid;
    plot(centroid_k(1), centroid_k(2), <span style="color: #A020F0">'b.'</span>);
<span style="color: #0000FF">end</span>
hold <span style="color: #A020F0">off</span></pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/dot_locations_03.png"> <p>Hmm. It looks we got only one dot at some of those locations.  Use the zoom button on the Figure Window toolbar to zoom in.
       Or you can do it noninteractively:
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">axis([50 100 0 50])</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/dot_locations_04.png"> <p>Yep. For overlapping circles, we are only getting one location. The reason is that the interiors of the overlapping circles
      are 8-connected to each other, so they are regarded by <tt>regionprops</tt> as single regions.  To get two locations for these overlapping circles, we have to label the regions using 4-connectivity
      instead of 8-connectivity.
   </p>
   <p>To do this we have to compute the connected components in a separate step and then call <tt>regionprops</tt>.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">cc = bwconncomp(bw, 4);
s = regionprops(cc, <span style="color: #A020F0">'Centroid'</span>);</pre><p><a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/bwconncomp.html"><tt>bwconncomp</tt></a> is also new to R2009a. Users of R2008b and earlier can do:
   </p><pre> L = bwlabel(bw, 4);
 s = regionprops(L, 'Centroid');</pre><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">imshow(X, map)
hold <span style="color: #A020F0">on</span>
<span style="color: #0000FF">for</span> k = 1:numel(s)
    centroid_k = s(k).Centroid;
    plot(centroid_k(1), centroid_k(2), <span style="color: #A020F0">'b.'</span>);
<span style="color: #0000FF">end</span>
hold <span style="color: #A020F0">off</span>
axis([50 100 0 50])</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/dot_locations_05.png"> <p>Much better.</p>
   <p>This little example showed several useful things:</p>
   <div>
      <ul>
         <li>Reading an image directly from a URL</li>
         <li>Using <tt>imtool</tt> to inspect individual pixel values
         </li>
         <li>Using the new, more efficient syntax of <tt>regionprops</tt></li>
         <li>Using the new <tt>bwconncomp</tt></li>
         <li>Superimposing plots on an image</li>
      </ul>
   </div>
   <p>Have a happy weekend!</p><script language="JavaScript">
<!--

    function grabCode_e948b6c7c06443fb92b2e2de280bed8f() {
        // 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='e948b6c7c06443fb92b2e2de280bed8f ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' e948b6c7c06443fb92b2e2de280bed8f';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_e948b6c7c06443fb92b2e2de280bed8f()"><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; 7.9<br /></p>
</div>
<!--
e948b6c7c06443fb92b2e2de280bed8f ##### SOURCE BEGIN #####
%%
% I was looking at the image below on a 
% <http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/alpha.html 
% web page> recently and I decided to
% extract the locations of all the dots. I thought the procedure might make a
% nice little end-of-the-week how-to post.

% Did you know that imread can read directly from a URL?
url = 'http://cgm.cs.mcgill.ca/~godfried/teaching/projects97/belair/example1.gif';
[X, map] = imread(url);
imshow(X, map)

%%
% First question to answer: What is the index of the color used for the dots?
% One easy way to go is to use 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/imtool.html |imtool|>.
%
% Here's a screenshot:
%
% <<http://blogs.mathworks.com/images/steve/2009/imtool-screen-shot.png>>
%
% As you can see, when I placed the mouse pointer over the center of one of the
% dots, the pixel info display at the lower left showed that the index value was
% 1, and the corresponding colormap color was [1.00, 0.78, 0.00].
%
% Now that we know the index value, we can easily make a binary image of just the interior
% of the dots.

bw = X == 1;
imshow(bw)

%%
% Now we can compute the centroids of the dots.

s = regionprops(bw, 'Centroid')

%%
% The line above is a new syntax for 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/regionprops.html 
% |regionprops|> that we introduced earlier
% this year in R2009a.  Previously, you always had to compute a label matrix
% first using 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/bwlabel.html 
% |bwlabel|> and then pass that label matrix to |regionprops|.  Now
% |regionprops| can do this computation directly on the binary image.  Since the
% label matrix is not computed, this new syntax uses less memory and usually
% runs faster than the old version.
%
% For those of you using an older version, do this instead:
%
%   L = bwlabel(bw);
%   s = regionprops(L, 'Centroid');
%
% To show the results, display the image and then superimpose the centroid
% locations.

imshow(X, map)
hold on
for k = 1:numel(s)
    centroid_k = s(k).Centroid;
    plot(centroid_k(1), centroid_k(2), 'b.');
end
hold off

%%
% Hmm. It looks we got only one dot at some of those locations.  Use the zoom
% button on the Figure Window toolbar to zoom in.  Or you can do it
% noninteractively:

axis([50 100 0 50])

%%
% Yep. For overlapping circles, we are only getting one location. The reason is
% that the interiors of the overlapping circles are 8-connected to each other,
% so they are regarded by |regionprops| as single regions.  To get two locations
% for these overlapping circles, we have to label the regions using
% 4-connectivity instead of 8-connectivity.
%
% To do this we have to compute the connected components in a separate step and
% then call |regionprops|.

cc = bwconncomp(bw, 4);
s = regionprops(cc, 'Centroid');

%%
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/bwconncomp.html 
% |bwconncomp|> is also new to R2009a. Users of R2008b and earlier can do:
%
%   L = bwlabel(bw, 4);
%   s = regionprops(L, 'Centroid');

imshow(X, map)
hold on
for k = 1:numel(s)
    centroid_k = s(k).Centroid;
    plot(centroid_k(1), centroid_k(2), 'b.');
end
hold off
axis([50 100 0 50])

%%
% Much better.
%
% This little example showed several useful things:
%
% * Reading an image directly from a URL
% * Using |imtool| to inspect individual pixel values
% * Using the new, more efficient syntax of |regionprops|
% * Using the new |bwconncomp|
% * Superimposing plots on an image
%
% Have a happy weekend!

##### SOURCE END ##### e948b6c7c06443fb92b2e2de280bed8f
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/G3rwjkJNQAM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/11/20/extracting-dot-locations-from-a-graphic/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/11/20/extracting-dot-locations-from-a-graphic/</feedburner:origLink></item>
		<item>
		<title>Maybe truecolor is OK after all</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/AKrcOlLKj6M/</link>
		<comments>http://blogs.mathworks.com/steve/2009/11/12/maybe-truecolor-is-ok-after-all/#comments</comments>
		<pubDate>Thu, 12 Nov 2009 18:14:09 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/11/12/maybe-truecolor-is-ok-after-all/</guid>
		<description><![CDATA[
   Yesterday I posted that I was looking for a replacement for the term truecolor.  (I won't repeat the explanation here; take a look at the original post.)  Quite a few readers posted interesting and thoughtful ideas.
   
   Gene commented and Rob sent me e-mail about the [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p><a href="http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/">Yesterday I posted</a> that I was looking for a replacement for the term <i>truecolor</i>.  (I won't repeat the explanation here; take a look at the <a href="http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/">original post</a>.)  Quite a few readers posted interesting and thoughtful ideas.
   </p>
   <p><a href="http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/#comment-22328">Gene commented</a> and <a href="http://www.mathworks.com/matlabcentral/fileexchange/authors/35927">Rob</a> sent me e-mail about the use of the term truecolor in remotely sensed imagery. I had been thinking about the term as defining
      a form of representation: each pixel is a vector of color-space component values.  They pointed out to me that a "truecolor
      image" in remote sensing has a more specific meaning: it is a three-band image in which the bands contain data from the red,
      green, and blue portions of the visible spectrum (in that order).
   </p>
   <p>That caused me to rethink things a little bit.  If I'm concerned about the distinction between different kinds of <i>representation</i>, then I can talk about a color image as being <i>multichannel</i> or <i>indexed</i>.  That leaves us able to use <i>truecolor</i> to refer a specific kind of multichannel color image.  And that has the advantage of leaving our existing doc mostly alone.
   </p>
   <p>What do you think?</p>
   <p>It interests me that my posts about terminology questions always seem to draw a lot of comment.  And I appreciate that each
      time I do it, you teach me good stuff.
   </p>
   <p>One of my favorite terminology stories is when <a href="http://www.hpl.hp.com/about/bios/ron_schafer.html">Prof. Ron Schafer</a> showed his class a <a href="http://en.wikipedia.org/wiki/Sniglet">"Sniglet."</a> (Sniglets, which are made-up words with plausible-sounding definitions, were popular in the 1980s.)  Since we were a digital
      signal processing class, we especially appreciated the definition of the Sniglet <i>point blimfark</i> - the point at which the stagecoach wheels in the movie start to look like they're going backward (otherwise known as <i>aliasing</i>).
   </p><script language="JavaScript">
<!--

    function grabCode_df3a9d1c526e44c4b391e8b53a8917c2() {
        // 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='df3a9d1c526e44c4b391e8b53a8917c2 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' df3a9d1c526e44c4b391e8b53a8917c2';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_df3a9d1c526e44c4b391e8b53a8917c2()"><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; 7.9<br /></p>
</div>
<!--
df3a9d1c526e44c4b391e8b53a8917c2 ##### SOURCE BEGIN #####
%%
% <http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/ 
% Yesterday I posted> that I was looking for a replacement for the term
% _truecolor_.  (I won't repeat the explanation here; take a look at the
% <http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/ 
% original post>.)  Quite a few readers posted interesting and thoughtful ideas. 
%
% <http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/#comment-22328 
% Gene commented> and <http://www.mathworks.com/matlabcentral/fileexchange/authors/35927 
% Rob> sent me e-mail about the use of the
% term truecolor in remotely sensed imagery. I had been thinking about the term
% as defining a form of representation: each pixel is a vector of color-space
% component values.  They pointed out to me that a "truecolor image" in remote sensing has
% a more specific meaning: it is a three-band image in which the bands contain
% data from the red, green, and blue portions of the visible spectrum (in that order).
%
% That caused me to rethink things a little bit.  If I'm concerned about the
% distinction between different kinds of _representation_, then I can talk about
% a color image as being _multichannel_ or _indexed_.  That leaves us able to
% use _truecolor_ to refer a specific kind of multichannel color image.  And
% that has the advantage of leaving our existing doc mostly alone.
%
% What do you think?
%
% It interests me that my posts about terminology questions always seem to draw a lot
% of comment.  And I appreciate that each time I do it, you teach me good stuff.
% 
% One of my favorite
% terminology stories is when <http://www.hpl.hp.com/about/bios/ron_schafer.html 
% Prof. Ron Schafer> showed his class a <http://en.wikipedia.org/wiki/Sniglet 
% "Sniglet."> (Sniglets, which are made-up words with plausible-sounding definitions,
% were popular in the 1980s.)  Since we were a digital signal processing class,
% we especially appreciated the definition of the Sniglet _point blimfark_ -
% the point at which the stagecoach wheels in the movie start to look like
% they're going backward (otherwise known as _aliasing_).
##### SOURCE END ##### df3a9d1c526e44c4b391e8b53a8917c2
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/AKrcOlLKj6M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/11/12/maybe-truecolor-is-ok-after-all/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/11/12/maybe-truecolor-is-ok-after-all/</feedburner:origLink></item>
		<item>
		<title>I’m looking for a replacement for “truecolor”</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/WZp6uTnfaHk/</link>
		<comments>http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/#comments</comments>
		<pubDate>Wed, 11 Nov 2009 15:31:18 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/</guid>
		<description><![CDATA[
   The Image Processing Toolbox has terminology conventions for four different image types:
   
      
         Binary images
         Gray-scale images
         Indexed images
  [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p>The Image Processing Toolbox has terminology conventions for four different image types:</p>
   <div>
      <ul>
         <li>Binary images</li>
         <li>Gray-scale images</li>
         <li>Indexed images</li>
         <li>Truecolor images</li>
      </ul>
   </div>
   <p>You'll also frequently see the term <i>RGB image</i>, which is shorthand for a truecolor image using an RGB color space.  (See the <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/f14-13543.html">User Guide section on image types</a>.)
   </p>
   <p>Over the last few years I've become increasingly dissatisfied with the term <i>truecolor</i>.
   </p>
   <p>Wikipedia has a <a href="http://en.wikipedia.org/wiki/Truecolor">brief article on truecolor</a>.  The article says the term describes a "method of representing and storing graphical image information."  It goes on to
      say that a truecolor representation is one that either:
   </p>
   <p>(a) can represent a large number of colors, typically at least 2^24.</p>
   <p>(b) does not use a color look-up table ("colormap" in MATLAB terminology)</p>
   <p>Curiously, the article refers to (a) and (b) as "equivalent" statements.</p>
   <p>Defining an image representation method in terms of whether it represents a lot of colors is too vague to be very useful in
      my view. Defining a representation in terms of a characteristic it does not possess (that is, a truecolor representation does
      not use a color look-up table) is similarly vague.
   </p>
   <p>Also, as I learn more about color science I've grown uncomfortable with the idea that any computer or mathematical representation
      of color can really be called "true color."
   </p>
   <p>Here's the definition I really want to see:</p>
   <p><i><b>[blank]</b> is a method of representing image information in which each image pixel is stored as a vector of color-space component values.</i></p>
   <p>But what's a good term to go along with this definition? Help me fill in the blank by commenting with your thoughts.</p><script language="JavaScript">
<!--

    function grabCode_c999f11ff9cd484aa896f5916b9d89c4() {
        // 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='c999f11ff9cd484aa896f5916b9d89c4 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' c999f11ff9cd484aa896f5916b9d89c4';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_c999f11ff9cd484aa896f5916b9d89c4()"><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; 7.9<br /></p>
</div>
<!--
c999f11ff9cd484aa896f5916b9d89c4 ##### SOURCE BEGIN #####
%%
% The Image Processing Toolbox has terminology conventions for four different
% image types:
%
% * Binary images
% * Gray-scale images
% * Indexed images
% * Truecolor images
%
% You'll also frequently see the term _RGB image_, which is shorthand for a
% truecolor image using an RGB color space.  (See the 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/f14-13543.html 
% User Guide section on image types>.)
%
% Over the last few years I've become increasingly dissatisfied with the term
% _truecolor_.
%
% Wikipedia has a <http://en.wikipedia.org/wiki/Truecolor brief article on
% truecolor>.  The article says the term describes a "method of representing and
% storing graphical image information."  It goes on to say that a truecolor
% representation is one that either:
%
% (a) can represent a large number of colors, typically at least 2^24.
%
% (b) does not use a color look-up table ("colormap" in MATLAB terminology)
%
% Curiously, the article refers to (a) and (b) as "equivalent" statements.
%
% Defining an image representation method in terms of whether it represents a
% lot of colors is too vague to be very useful in my view. Defining a representation
% in terms of a characteristic it does not possess (that is, a truecolor
% representation does not use a color look-up table) is similarly vague.
%
% Also, as I learn more about color science I've grown uncomfortable with the
% idea that any computer or mathematical representation of color can really be
% called "true color."
%
% Here's the definition I really want to see:
%
% _*[blank]* is a method of representing image information in which each image
% pixel is stored as a vector of color-space component values._
%
% But what's a good term to go along with this definition? Help me fill in the
% blank by commenting with your thoughts.

##### SOURCE END ##### c999f11ff9cd484aa896f5916b9d89c4
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/WZp6uTnfaHk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/11/11/im-looking-for-a-replacement-for-truecolor/</feedburner:origLink></item>
		<item>
		<title>Writing TIFF files with given width and resolution</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/lE35Ziosde0/</link>
		<comments>http://blogs.mathworks.com/steve/2009/11/09/writing-tiff-files-with-given-width-and-resolution/#comments</comments>
		<pubDate>Mon, 09 Nov 2009 15:35:10 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/11/09/writing-tiff-files-with-given-width-and-resolution/</guid>
		<description><![CDATA[
   I received the following question recently:
   I'd like to be able to establish an image size that will be recognized by PDFLATEX when I compile my document. Often, I size
         an image in MATLAB only to have it occupy more than a [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p>I received the following question recently:</p>
   <p><i>I'd like to be able to establish an image size that will be recognized by PDFLATEX when I compile my document. Often, I size
         an image in MATLAB only to have it occupy more than a page after compiling in PDFLATEX. I know I can use imresize, but I'd
         like to resize a PNG so that it is exact 2 inches wide, so I can get some consistency of sizing in my document.</i></p>
   <p>It occurred to me that this is a common use case in publishing articles, books, etc: "I need this image to print exactly 3
      inches wide in my document so it fits nicely in the column."  The document might be LaTeX as above, or a Word file, or something
      else.
   </p>
   <p>In publishing, TIFF is usually the format of choice.  The MATLAB function <tt>imwrite</tt> can include extra information in the TIFF file to control how wide an image will be printed when included in a document application.
       This extra information is provided in the form of the <tt>'Resolution'</tt> parameter, which gives pixels per inch.  (In this context the term dots per inch is also used.)
   </p>
   <p>I wrote about how to use the <tt>'Resolution'</tt> parameter <a href="http://blogs.mathworks.com/steve/2006/03/03/help-my-publisher-wants-a-300-dpi-tiff/">way back in 2006</a>, but at the time I didn't explain how to achieve a certain desired printed width.
   </p>
   <p>When publishers specify a certain resolution in pixels per inch (dots per inch), <i>and</i> the image should be printed at a certain width, then generally the image has to be resized to meet both criteria.  That is,
      the number of image pixels may have to be changed.
   </p>
   <p>To help users prepare such image files I wrote the MATLAB function <a href="http://www.mathworks.com/matlabcentral/fileexchange/25595-imwritesize-write-image-file-with-specified-width-and-resolution"><tt>imwritesize</tt></a>, which you can find on the <a href="http://www.mathworks.com/matlabcentral/fileexchange/25595-imwritesize-write-image-file-with-specified-width-and-resolution">MATLAB Central File Exchange</a>.
   </p>
   <p>In the most simple usage, <tt>imwritesize</tt> will create a TIFF file or PNG file for you so that the image will have the desired width in a document application.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">rgb = imread(<span style="color: #A020F0">'peppers.png'</span>);
size(rgb)</pre><pre style="font-style:oblique">
ans =

   384   512     3

</pre><p>Notice the original image has 512 pixels per row.</p>
   <p>Now write the image out using <tt>imwritesize</tt>:
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">imwritesize(rgb, <span style="color: #A020F0">'peppers_3in.tif'</span>, 3);</pre><p>The extension of the output filename determines the image file format.  To write out a PNG file instead of TIFF, just use
      the extension '.png'.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">imwritesize(rgb, <span style="color: #A020F0">'peppers_3in.png'</span>, 3);</pre><p>With this usage, the number of pixels in the image is not changed. <tt>imwritesize</tt> just saves the image into the file with the right resolution parameter to achieve the desired width;
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">info = imfinfo(<span style="color: #A020F0">'peppers_3in.tif'</span>);
image_pixels_per_row = info.Width</pre><pre style="font-style:oblique">
image_pixels_per_row =

   512

</pre><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">document_width_in_inches = image_pixels_per_row / info.XResolution</pre><pre style="font-style:oblique">
document_width_in_inches =

   2.994152046783626

</pre><p>The width is not exactly 3 inches because the resolution value in a TIFF file is restricted to be an integer number of pixels
      per inch.
   </p>
   <p>Now suppose you want the document width of the image to be 3 inches <b>and</b> the document image resolution to be 300 dpi?  Then you specify 300 as an additional argument to <tt>imwritesize</tt>:
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">imwritesize(rgb, <span style="color: #A020F0">'peppers_3in_at_300dpi.tif'</span>, 3, 300);</pre><p>With this usage, the number of image pixels is changed by calling <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/imresize.html"><tt>imresize</tt></a>, an Image Processing Toolbox function.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">info2 = imfinfo(<span style="color: #A020F0">'peppers_3in_at_300dpi.tif'</span>);
image_pixels_per_row = info2.Width</pre><pre style="font-style:oblique">
image_pixels_per_row =

   900

</pre><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">document_width_in_inches = image_pixels_per_row / info2.XResolution</pre><pre style="font-style:oblique">
document_width_in_inches =

     3

</pre><p>I apologize to those of you living in metric land.  I wanted to keep the interface simple so I did not include units options.
       You could perform a metric conversion in the call to <tt>imwritesize</tt>, like this:
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">imwritesize(rgb, <span style="color: #A020F0">'peppers_7cm.tif'</span>, 7/2.54)</pre><p>Or you can modify the code in <tt>imwritesize</tt> to suit yourself.  I tried to keep the code very straightforward so that users could learn from it.
   </p>
   <p>I hope you find this MATLAB Central File Exchange contribution useful.  If you want to use this function and you already have
      MATLAB R2009b, you should consider taking this chance to experiment with the new <a href="http://blogs.mathworks.com/desktop/2009/09/21/the-front-page-of-the-file-exchange-your-desktop/">MATLAB Desktop / File Exchange integration</a>.
   </p><script language="JavaScript">
<!--

    function grabCode_f665d66061c94faaa4c41c7c8bb926af() {
        // 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='f665d66061c94faaa4c41c7c8bb926af ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' f665d66061c94faaa4c41c7c8bb926af';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_f665d66061c94faaa4c41c7c8bb926af()"><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; 7.9<br /></p>
</div>
<!--
f665d66061c94faaa4c41c7c8bb926af ##### SOURCE BEGIN #####
%%
% I received the following question recently:
%
% _I'd like to be able to establish an image size that will be recognized by
% PDFLATEX when I compile my document. Often, I size an image in MATLAB only to
% have it occupy more than a page after compiling in PDFLATEX. I know I can use
% imresize, but I'd like to resize a PNG so that it is exact 2 inches wide, so
% I can get some consistency of sizing in my document._
%
% It occurred to me that this is a common use case in publishing articles,
% books, etc: "I need this image to print exactly 3 inches wide in my document
% so it fits nicely in the column."  The document might be LaTeX as above, or a
% Word file, or something else.
%
% In publishing, TIFF is usually the format of choice.  The MATLAB function
% |imwrite| can include extra information in the TIFF file to control how wide
% an image will be printed when included in a document application.  This extra
% information is provided in the form of the |'Resolution'| parameter, which
% gives pixels per inch.  (In this context the term dots per inch is also used.)
% 
% I wrote about how to use the |'Resolution'| parameter 
% <http://blogs.mathworks.com/steve/2006/03/03/help-my-publisher-wants-a-300-dpi-tiff/ 
% way back in 2006>, but at the time I didn't explain how to achieve a certain
% desired printed width.
%
% When publishers specify a certain resolution in pixels per inch (dots per
% inch), _and_ the image should be printed at a certain width, then generally
% the image has to be resized to meet both criteria.  That is, the number of
% image pixels may have to be changed.
%
% To help users prepare such image files I wrote the MATLAB function
% <http://www.mathworks.com/matlabcentral/fileexchange/25595-imwritesize-write-image-file-with-specified-width-and-resolution 
% |imwritesize|>, which you can find on the 
% <http://www.mathworks.com/matlabcentral/fileexchange/25595-imwritesize-write-image-file-with-specified-width-and-resolution 
% MATLAB Central File Exchange>.
%
% In the most simple usage, |imwritesize| will create a TIFF file or PNG file
% for you so that the image will have the desired width in a document
% application.

rgb = imread('peppers.png');
size(rgb)

%%
% Notice the original image has 512 pixels per row.
%
% Now write the image out using |imwritesize|:

imwritesize(rgb, 'peppers_3in.tif', 3);

%%
% The extension of the output filename determines the image file format.  To
% write out a PNG file instead of TIFF, just use the extension '.png'.

imwritesize(rgb, 'peppers_3in.png', 3);

%%
% With this usage, the number of pixels in the image is not changed.
% |imwritesize| just saves the image into the file with the right resolution
% parameter to achieve the desired width;

info = imfinfo('peppers_3in.tif');
image_pixels_per_row = info.Width

%%
document_width_in_inches = image_pixels_per_row / info.XResolution

%%
% The width is not exactly 3 inches because the resolution value in a TIFF file
% is restricted to be an integer number of pixels per inch.
%
% Now suppose you want the document width of the image to be 3 inches *and* the
% document image resolution to be 300 dpi?  Then you specify 300 as an
% additional argument to |imwritesize|:

imwritesize(rgb, 'peppers_3in_at_300dpi.tif', 3, 300);

%%
% With this usage, the number of image pixels is changed by calling 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/imresize.html 
% |imresize|>, an Image Processing Toolbox function.

%%
info2 = imfinfo('peppers_3in_at_300dpi.tif');
image_pixels_per_row = info2.Width

%%
document_width_in_inches = image_pixels_per_row / info2.XResolution

%%
% I apologize to those of you living in metric land.  I wanted to keep the
% interface simple so I did not include units options.  You could perform a
% metric conversion in the call to |imwritesize|, like this:

imwritesize(rgb, 'peppers_7cm.tif', 7/2.54)

%%
% Or you can modify the code in |imwritesize| to suit yourself.  I tried to keep
% the code very straightforward so that users could learn from it.
%
% I hope you find this MATLAB Central File Exchange contribution useful.  If you
% want to use this function and you already have MATLAB R2009b, you should
% consider taking this chance to experiment with the new 
% <http://blogs.mathworks.com/desktop/2009/09/21/the-front-page-of-the-file-exchange-your-desktop/ 
% MATLAB Desktop / File Exchange integration>.

##### SOURCE END ##### f665d66061c94faaa4c41c7c8bb926af
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/lE35Ziosde0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/11/09/writing-tiff-files-with-given-width-and-resolution/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/11/09/writing-tiff-files-with-given-width-and-resolution/</feedburner:origLink></item>
		<item>
		<title>The conv function and implementation tradeoffs</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/Snab-x9cEHk/</link>
		<comments>http://blogs.mathworks.com/steve/2009/11/03/the-conv-function-and-implementation-tradeoffs/#comments</comments>
		<pubDate>Tue, 03 Nov 2009 14:56:58 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/11/03/the-conv-function-and-implementation-tradeoffs/</guid>
		<description><![CDATA[
   A friend from my grad school days (back in the previous millenium) is an electrical engineering professor.  Students in his
      class recently asked him why the conv function is not implemented using FFTs.
   
   I'm not on the team responsible for conv, [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p>A friend from my grad school days (back in the previous millenium) is an electrical engineering professor.  Students in his
      class recently asked him why the <tt>conv</tt> function is not implemented using FFTs.
   </p>
   <p>I'm not on the team responsible for <tt>conv</tt>, but I wrote back with my thoughts, and I thought I would share them here as well.
   </p>
   <p>Let's review the basics.  Using the typical convolution formula to compute the one-dimensional convolution of a P-element
      sequence A with Q-element sequence B has a computational complexity of <img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/fft_based_conv_eq04674.png"> .  However, the discrete Fourier transform (DFT) can be used to implement convolution as follows:
   </p>
   <p>1. Compute the L-point DFT of A, where <img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/fft_based_conv_eq40865.png"> .
   </p>
   <p>2. Compute the L-point DFT of B.</p>
   <p>3. Multiply the two DFTs.</p>
   <p>4. Compute the inverse DFT to get the convolution.</p>
   <p>Here's a simple MATLAB function for computing convolution using the Fast Fourier Transform (FFT), which is simply a fast algorithm
      for computing the DFT.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">type <span style="color: #A020F0">conv_fft</span></pre><pre style="font-style:oblique">
function c = conv_fft(a, b)

P = numel(a);
Q = numel(b);
L = P + Q - 1;
K = 2^nextpow2(L);

c = ifft(fft(a, K) .* fft(b, K));
c = c(1:L);

</pre><p>Note that the code uses the next power-of-two greater than or equal to L, although this is not strictly necessary. The <tt>fft</tt> function operates in <img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/fft_based_conv_eq00311.png">  time whether or not L is a power of two.
   </p>
   <p>The overall computational complexity of these steps is <img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/fft_based_conv_eq47887.png"> . For P and Q sufficiently large, then, using the DFT to implement convolution is a computational win.
   </p>
   <p>So why don't we do it?</p>
   <p>There are several technical factors. Let's look at speed, exact computation, and memory.</p>
   <p><b>Speed</b></p>
   <p>One factor is that DFT-based computation is not <b>always</b> faster.  Let's do an experiment where we compute the convolution of a 1000-element sequence with another sequence of varying
      length. (Get the <tt>timeit</tt> function from the <a href="http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function">MATLAB Central File Exchange</a>.)
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">x = rand(1, 1000);
nn = 25:25:1000;

t_normal = zeros(size(nn));
t_fft = zeros(size(nn));

<span style="color: #0000FF">for</span> k = 1:numel(nn)
    n = nn(k);
    y = rand(1, n);
    t_normal(k) = timeit(@() conv(x, y));
    t_fft(k) = timeit(@() conv_fft(x, y));
<span style="color: #0000FF">end</span></pre><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">plot(nn, t_normal, nn, t_fft)
legend({<span style="color: #A020F0">'Normal computation'</span>, <span style="color: #A020F0">'FFT-based computation'</span>})</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/fft_based_conv_01.png"> <p>For sequences <tt>y</tt> shorter than a certain length, called the <i>cross-over point</i>, it's quicker to use the normal computation.
   </p>
   <p><b>Exact computation</b></p>
   <p>A second consideration is whether the computation is subject to floating-point round-off errors and to what degree.  There
      are applications, for example, where the convolution of integer-valued sequences is computed.  For such applications, a user
      would reasonably expect the output sequence to be integer-valued as well.
   </p>
   <p>To illustrate, here's a simple function that computes <a href="http://en.wikipedia.org/wiki/Binomial_coefficient">n-th order binomial coefficients</a> using convolution:
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">type <span style="color: #A020F0">binom</span></pre><pre style="font-style:oblique">
function c = binom(n)

c = 1;
for k = 1:n
    c = conv(c, [1 1]);
end

</pre><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">binom(7)</pre><pre style="font-style:oblique">
ans =

     1     7    21    35    35    21     7     1

</pre><p>I wrote a variation called <tt>binom_fft</tt> that is the same as <tt>binom</tt> except that it calls <tt>conv_fft</tt>.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">format <span style="color: #A020F0">long</span>
binom_fft(7)</pre><pre style="font-style:oblique">
ans =

  Columns 1 through 4

   1.000000000000000   6.999999999999998  21.000000000000000  35.000000000000000

  Columns 5 through 8

  35.000000000000000  21.000000000000000   7.000000000000000   0.999999999999996

</pre><p>Whoops! What's going on? The answer is that the FFT-based implementation of convolution is subject to floating-point round-off
      error.
   </p>
   <p>I imagine that most MATLAB users would consider the output of <tt>binom_fft</tt> to be <b>wrong</b>.
   </p>
   <p><b>Memory</b></p>
   <p>The last technical consideration I want to mention is memory.  Because of the padding and complex arithmetic involved in the
      FFT computations, the FFT-based convolution implementation requires a lot more memory than the normal computation. This may
      not often be a problem for one-dimensional computations, but it can be a big deal for multidimensional computations.
   </p>
   <p><b>Final thoughts</b></p>
   <p>The technical considerations listed above can all be solved in principle.  The implementation could switch to using the normal
      method for short or integer-valued sequences, for example. And there are FFT-based techniques such as <a href="http://en.wikipedia.org/wiki/Overlap-add_method">overlap-and-add</a> to reduce the memory load.
   </p>
   <p>But the problem can get quite complicated.  Testing floating-point values to see if they are integers, for example, can be
      slow.  Also, I suspect (but have not checked) that a multithreaded implemention of the normal computation will take advantage
      of multiple cores better than a multithreaded FFT-based method. That would change the cross-over point between the two methods.
      And the exact cross-over point will vary from computer to computer, making it likely that our implementation would be somewhat
      slower for some people for some problems.
   </p>
   <p>Overall, my inclination would be to provide FFT-based convolution as a separate function rather than reimplementing <tt>conv</tt>.  And that's what we've done. See the function <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/signal/fftfilt.html"><tt>fftfilt</tt></a> in the Signal Processing Toolbox.
   </p>
   <p>Do you disagree with this approach?  Post your comment.</p><script language="JavaScript">
<!--

    function grabCode_2a1830f6070e4f9bb82cb33b602509a3() {
        // 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='2a1830f6070e4f9bb82cb33b602509a3 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 2a1830f6070e4f9bb82cb33b602509a3';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_2a1830f6070e4f9bb82cb33b602509a3()"><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; 7.9<br /></p>
</div>
<!--
2a1830f6070e4f9bb82cb33b602509a3 ##### SOURCE BEGIN #####
%%
% A friend from my grad school days (back in the previous millenium) is an
% electrical engineering professor.  Students in his class recently asked him
% why the |conv| function is not implemented using FFTs.
%
% I'm not on the team responsible for |conv|, but I wrote back with my
% thoughts, and I thought I would share them here as well.
%
% Let's review the basics.  Using the typical convolution formula to compute the
% one-dimensional convolution of a P-element sequence A with Q-element sequence
% B has a computational complexity of $O(PQ)$.  However, the discrete Fourier transform (DFT)
% can be used to implement convolution as follows:
%
% 1. Compute the L-point DFT of A, where $L \geq P + Q - 1$.
%
% 2. Compute the L-point DFT of B.
% 
% 3. Multiply the two DFTs.
%
% 4. Compute the inverse DFT to get the convolution.
%
% Here's a simple MATLAB function for computing convolution using the Fast
% Fourier Transform (FFT), which is simply a fast algorithm for computing the
% DFT.

type conv_fft

%%
% Note that the code uses the next power-of-two greater than or equal to L,
% although this is not strictly necessary. The |fft| function operates in $L
% \log L$ time whether or not L is a power of two.
%
% The overall computational complexity of these steps is $O(L\log L)$. For P and
% Q sufficiently large, then, using the DFT to implement convolution is a
% computational win.
%
% So why don't we do it?
%
% There are several technical factors. Let's look at speed, exact computation,
% and memory.

%% 
% *Speed*
%
% One factor is that DFT-based computation is not *always* faster.  Let's do an
% experiment where we compute the convolution of a 1000-element sequence with
% another sequence of varying length. (Get the |timeit| function from the 
% <http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function 
% MATLAB Central File Exchange>.)

x = rand(1, 1000);
nn = 25:25:1000;

t_normal = zeros(size(nn));
t_fft = zeros(size(nn));

for k = 1:numel(nn)
    n = nn(k);
    y = rand(1, n);
    t_normal(k) = timeit(@() conv(x, y));
    t_fft(k) = timeit(@() conv_fft(x, y));
end

%%
plot(nn, t_normal, nn, t_fft)
legend({'Normal computation', 'FFT-based computation'})

%%
% For sequences |y| shorter than a certain length, called the _cross-over
% point_, it's quicker to use the normal computation.

%% 
% *Exact computation*
%
% A second consideration is whether the computation is subject to floating-point
% round-off errors and to what degree.  There are applications, for example,
% where the convolution of integer-valued sequences is computed.  For such
% applications, a user would reasonably expect the output sequence to be
% integer-valued as well.
%
% To illustrate, here's a simple function that computes 
% <http://en.wikipedia.org/wiki/Binomial_coefficient n-th order binomial
% coefficients> using convolution:

type binom

%%
binom(7)

%%
% I wrote a variation called |binom_fft| that is the same as |binom| except that
% it calls |conv_fft|.

format long
binom_fft(7)

%%
% Whoops! What's going on? The answer is that the FFT-based implementation of
% convolution is subject to floating-point round-off error.
%
% I imagine that most MATLAB users would consider the output of |binom_fft| to
% be *wrong*.

%% 
% *Memory*
%
% The last technical consideration I want to mention is memory.  Because of the
% padding and complex arithmetic involved in the FFT computations, the FFT-based
% convolution implementation requires a lot more memory than the normal
% computation. This may not often be a problem for one-dimensional computations,
% but it can be a big deal for multidimensional computations.

%% 
% *Final thoughts*
%
% The technical considerations listed above can all be solved in principle.  The
% implementation could switch to using the normal method for short or
% integer-valued sequences, for example. And there are FFT-based techniques such as
% <http://en.wikipedia.org/wiki/Overlap-add_method overlap-and-add> to reduce
% the memory load.  
% 
% But the problem can get quite complicated.  Testing floating-point values to
% see if they are integers, for example, can be slow.  Also, I suspect (but have
% not checked) that a multithreaded implemention of the normal computation will
% take advantage of multiple cores better than a multithreaded FFT-based method.
% That would change the cross-over point between the two methods. And the exact
% cross-over point will vary from computer to computer, making it likely that
% our implementation would be somewhat slower for some people for some problems.
%
% Overall, my inclination would be to provide FFT-based convolution as a
% separate function rather than reimplementing |conv|.  And that's what we've
% done. See the function 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/signal/fftfilt.html 
% |fftfilt|> in the Signal Processing Toolbox.
%
% Do you disagree with this approach?  Post your comment.
##### SOURCE END ##### 2a1830f6070e4f9bb82cb33b602509a3
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/Snab-x9cEHk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/11/03/the-conv-function-and-implementation-tradeoffs/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/11/03/the-conv-function-and-implementation-tradeoffs/</feedburner:origLink></item>
		<item>
		<title>Embedding an ICC profile into a TIFF file</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/ixEWbRIZWUE/</link>
		<comments>http://blogs.mathworks.com/steve/2009/10/20/embedding-an-icc-profile-into-a-tiff-file/#comments</comments>
		<pubDate>Tue, 20 Oct 2009 13:15:38 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/10/20/embedding-an-icc-profile-into-a-tiff-file/</guid>
		<description><![CDATA[
   The R2009b release of MATLAB contains a new Tiff class.  The primary purpose of this class is to provide lower-level access to creating and modifying image data and metadata in
      an existing TIFF file.
   
   Several customers have asked for the ability [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p>The R2009b release of MATLAB contains a new <a href="http://www.mathworks.com/access/helpdesk/help/techdoc/import_export/f5-123068.html#br_c_iz-1">Tiff class</a>.  The primary purpose of this class is to provide lower-level access to creating and modifying image data and metadata in
      an existing TIFF file.
   </p>
   <p>Several customers have asked for the ability to embed an ICC profile into a TIFF file.  The Image Processing Toolbox function
      <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/index.html?/access/helpdesk/help/toolbox/images/iccread.html"><tt>iccread</tt></a> can read a profile embedded in a TIFF file, but <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/index.html?/access/helpdesk/help/toolbox/images/iccwrite.html"><tt>iccwrite</tt></a> can only write a stand-alone profile file.
   </p>
   <p>Here is code using the new Tiff class to embed a profile in an existing TIFF file. Let's start by rewriting one of the Image
      Processing Toolbox sample PNG image files as a TIFF file.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">rgb = imread(<span style="color: #A020F0">'peppers.png'</span>);
imwrite(rgb, <span style="color: #A020F0">'peppers.tif'</span>);
s = dir(<span style="color: #A020F0">'peppers.tif'</span>)</pre><pre style="font-style:oblique">
s = 

       name: 'peppers.tif'
       date: '20-Oct-2009 09:14:29'
      bytes: 593880
      isdir: 0
    datenum: 7.3407e+005

</pre><p>Now let's embed the sample profile sRGB.icm into the TIFF file we just made.</p>
   <p>Step 1. Read in the raw bytes of the profile file.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">fid = fopen(<span style="color: #A020F0">'sRGB.icm'</span>);
raw_profile_bytes = fread(fid, Inf, <span style="color: #A020F0">'uint8=&gt;uint8'</span>);
fclose(fid);</pre><p>Step 2. Initialize a Tiff object using 'r+' mode (read and modify).</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">tif = Tiff(<span style="color: #A020F0">'peppers.tif'</span>, <span style="color: #A020F0">'r+'</span>)</pre><pre style="font-style:oblique">
tif = 

                  TIFF File: 'peppers.tif'
                       Mode: 'r+'
    Current Image Directory: 1
           Number Of Strips: 77
                SubFileType: Tiff.SubFileType.Default
                Photometric: Tiff.Photometric.RGB
                ImageLength: 384
                 ImageWidth: 512
               RowsPerStrip: 5
              BitsPerSample: 8
                Compression: Tiff.Compression.PackBits
               SampleFormat: Tiff.SampleFormat.UInt
            SamplesPerPixel: 3
        PlanarConfiguration: Tiff.PlanarConfiguration.Chunky
                Orientation: Tiff.Orientation.TopLeft

</pre><p>Step 3. Embed the profile bytes as a TIFF tag.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">tif.setTag(<span style="color: #A020F0">'ICCProfile'</span>, raw_profile_bytes);</pre><p>Step 4. Tell the Tiff object to update the image metadata in the file.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">tif.rewriteDirectory();</pre><p>Step 5. Close the Tiff object.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">tif.close();</pre><p>Now the TIFF file contains the profile. Notice the file size has changed.</p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">s = dir(<span style="color: #A020F0">'peppers.tif'</span>)</pre><pre style="font-style:oblique">
s = 

       name: 'peppers.tif'
       date: '20-Oct-2009 09:14:30'
      bytes: 597828
      isdir: 0
    datenum: 7.3407e+005

</pre><p>And we can read in the profile using <tt>iccread</tt>.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">p = iccread(<span style="color: #A020F0">'peppers.tif'</span>)</pre><pre style="font-style:oblique">
p = 

               Header: [1x1 struct]
             TagTable: {17x3 cell}
            Copyright: 'Copyright (c) 1999 Hewlett-Packard Company'
          Description: [1x1 struct]
      MediaWhitePoint: [0.9505 1 1.0891]
      MediaBlackPoint: [0 0 0]
        DeviceMfgDesc: [1x1 struct]
      DeviceModelDesc: [1x1 struct]
      ViewingCondDesc: [1x1 struct]
    ViewingConditions: [1x1 struct]
            Luminance: [76.0365 80 87.1246]
          Measurement: [1x1 struct]
           Technology: 'Cathode Ray Tube Display'
               MatTRC: [1x1 struct]
          PrivateTags: {}
             Filename: 'peppers.tif'

</pre><p>It would be logical to enhance <tt>iccwrite</tt> to make this easier for you. We'll look into that, although I'm not sure when that might happen.
   </p><script language="JavaScript">
<!--

    function grabCode_9eb468b777734c0285ee9b48dff42d03() {
        // 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='9eb468b777734c0285ee9b48dff42d03 ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' 9eb468b777734c0285ee9b48dff42d03';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_9eb468b777734c0285ee9b48dff42d03()"><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; 7.9<br /></p>
</div>
<!--
9eb468b777734c0285ee9b48dff42d03 ##### SOURCE BEGIN #####
%%
% The R2009b release of MATLAB contains a new 
% <http://www.mathworks.com/access/helpdesk/help/techdoc/import_export/f5-123068.html#br_c_iz-1 
% Tiff class>.  The primary purpose
% of this class is to provide lower-level access to creating and modifying
% image data and metadata in an existing TIFF file.
%
% Several customers have asked for the ability to embed an ICC profile into a
% TIFF file.  The Image Processing Toolbox function 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/index.html?/access/helpdesk/help/toolbox/images/iccread.html 
% |iccread|> can read a profile
% embedded in a TIFF file, but 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/index.html?/access/helpdesk/help/toolbox/images/iccwrite.html 
% |iccwrite|> can only write a stand-alone profile
% file.
%
% Here is code using the new Tiff class to embed a profile in an existing TIFF
% file. Let's start by rewriting one of the Image Processing Toolbox sample
% PNG image files as a TIFF file.

rgb = imread('peppers.png');
imwrite(rgb, 'peppers.tif');
s = dir('peppers.tif')

%%
% Now let's embed the sample profile sRGB.icm into the TIFF file we just made.
%
% Step 1. Read in the raw bytes of the profile file.
fid = fopen('sRGB.icm');
raw_profile_bytes = fread(fid, Inf, 'uint8=>uint8');
fclose(fid);

%%
% Step 2. Initialize a Tiff object using 'r+' mode (read and modify).
tif = Tiff('peppers.tif', 'r+')

%%
% Step 3. Embed the profile bytes as a TIFF tag.
tif.setTag('ICCProfile', raw_profile_bytes);

%%
% Step 4. Tell the Tiff object to update the image metadata in the file.
tif.rewriteDirectory();

%%
% Step 5. Close the Tiff object.
tif.close();

%%
% Now the TIFF file contains the profile. Notice the file size has changed.
s = dir('peppers.tif')

%%
% And we can read in the profile using |iccread|.
p = iccread('peppers.tif')

%%
% It would be logical to enhance |iccwrite| to make this easier for you. We'll look
% into that, although I'm not sure when that might happen.
##### SOURCE END ##### 9eb468b777734c0285ee9b48dff42d03
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/ixEWbRIZWUE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/10/20/embedding-an-icc-profile-into-a-tiff-file/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/10/20/embedding-an-icc-profile-into-a-tiff-file/</feedburner:origLink></item>
		<item>
		<title>Faster morphological reconstruction in R2009b</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/goLR2XpBknQ/</link>
		<comments>http://blogs.mathworks.com/steve/2009/10/19/faster-imreconstruct-in-r2009b/#comments</comments>
		<pubDate>Mon, 19 Oct 2009 07:00:36 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/10/19/faster-imreconstruct-in-r2009b/</guid>
		<description><![CDATA[
   We've been working for a while now to make Image Processing Toolbox functions run faster.  The R2009b release notes mention several performance improvements.  We've gotten some feedback, though, that our release notes are pretty vague about
      the improvements.  I can't argue with that impression. [...]]]></description>
			<content:encoded><![CDATA[<div xmlns:mwsh="http://www.mathworks.com/namespace/mcode/v1/syntaxhighlight.dtd" class="content">
   <p>We've been working for a while now to make Image Processing Toolbox functions run faster.  The <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/rn/rn_intro.html">R2009b release notes</a> mention several performance improvements.  We've gotten some feedback, though, that our release notes are pretty vague about
      the improvements.  I can't argue with that impression.  We tend to be vague because performance optimization is a very complex
      topic, and it can be quite difficult to characterize performance changes in a way that is brief, understandable, and accurate
      for every user's own hardware and data.
   </p>
   <p>But I've decided to start posting more detailed information here about the performance improvements.  I have more flexibility
      (and room!) here than we have with the release notes.
   </p>
   <p>Today I'll tackle <a href="http://www.mathworks.com/access/helpdesk/help/toolbox/images/index.html?/access/helpdesk/help/toolbox/images/imreconstruct.html"><tt>imreconstruct</tt></a>, which performs morphological reconstruction.  Reconstruction is a very useful operation that I've written about here before.
       For example, see my <a href="http://blogs.mathworks.com/steve/2008/07/14/opening-by-reconstruction/">post from last year on opening by reconstruction</a>.  Several other Image Processing Toolbox functions call <tt>imreconstruct</tt>, including <tt>imclearborder</tt>, <tt>imfill</tt>, <tt>imhmax</tt>, <tt>imhmin</tt>, <tt>imextendedmax</tt>, <tt>imextendedmin</tt>, and <tt>imimposemin</tt>.
   </p>
   <p>Let me use the <a href="http://blogs.mathworks.com/steve/2008/07/14/opening-by-reconstruction/">opening by reconstruction example</a> as a benchmark case.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">url = <span style="color: #A020F0">'http://blogs.mathworks.com/images/steve/2008/book_text.png'</span>;
text = imread(url);
imshow(text, <span style="color: #A020F0">'InitialMagnification'</span>, 25)
title(<span style="color: #A020F0">'918-by-2018 image displayed at 25% magnification'</span>)</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/imreconstruct_performance_01.png"> <p>The example task was to find letters containing vertical strokes by eroding with a vertical structuring element and then performing
      reconstruction.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">se = strel(ones(51, 1));
marker = imerode(text, se);
text2 = imreconstruct(marker, text);
imshow(text2, <span style="color: #A020F0">'InitialMagnification'</span>, 25)
title(<span style="color: #A020F0">'Output image displayed at 25% magnification'</span>)</pre><img vspace="5" hspace="5" src="http://blogs.mathworks.com/images/steve/2009/imreconstruct_performance_02.png"> <p>So how long does that call to <tt>imreconstruct</tt> take in R2009b?  I'll use my function <a href="http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function"><tt>timeit</tt></a>, which you can download from the MATLAB Central File Exchange.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">timeit(@() imreconstruct(marker, text))</pre><pre style="font-style:oblique">
ans =

    0.0241

</pre><p>That time is about 45 times faster than the same operation performed in R2009a.  Note that I'm running on two-core computer;
      the improved <tt>imreconstruct</tt> is multithreaded, so the performance improvement would be greater on a four-core computer, for example.
   </p>
   <p>Now let's time gray-scale reconstruction.  I'll make a 1024-by-1024 test image and compute a marker image by subtraction.
       This kind of operation is often used to suppress small peaks in an image.
   </p><pre style="background: #F9F7F3; padding: 10px; border: 1px solid rgb(200,200,200)">I = repmat(imread(<span style="color: #A020F0">'rice.png'</span>), 4, 4);
marker = I - 20;
timeit(@() imreconstruct(marker, I))</pre><pre style="font-style:oblique">
ans =

    0.0201

</pre><p>This time is about 30 times faster than R2009a, again running on my two-core laptop.</p>
   <p>Now for some key caveats you should know.  For now, the performance improvements described here only work for 2-D inputs that
      are uint8, uint16, or single, and only when the specified connectivity is 4 or 8.  We'll be working in the future to extend
      the speed improvements to other inputs.
   </p><script language="JavaScript">
<!--

    function grabCode_b2a3075faf7d470d90cb0c77ce2782fa() {
        // 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='b2a3075faf7d470d90cb0c77ce2782fa ' + '##### ' + 'SOURCE BEGIN' + ' #####';
        t2='##### ' + 'SOURCE END' + ' #####' + ' b2a3075faf7d470d90cb0c77ce2782fa';
    
        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;');

        author = '';
        copyright = 'Copyright 2009 The MathWorks, Inc.';

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

        // Add author and copyright lines at the bottom if specified.
        if ((author.length > 0) || (copyright.length > 0)) {
            d.writeln('');
            d.writeln('%%');
            if (author.length > 0) {
                d.writeln('% _' + author + '_');
            }
            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_b2a3075faf7d470d90cb0c77ce2782fa()"><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; 7.9<br /></p>
</div>
<!--
b2a3075faf7d470d90cb0c77ce2782fa ##### SOURCE BEGIN #####
%%
% We've been working for a while now to make Image Processing Toolbox functions
% run faster.  The 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/rn/rn_intro.html 
% R2009b release notes> mention several performance
% improvements.  We've gotten some feedback, though, that our release notes are
% pretty vague about the improvements.  I can't argue with that impression.  We tend
% to be vague because performance optimization is a very complex topic, and it
% can be quite difficult to characterize performance changes in a way that is
% brief, understandable, and accurate for every user's own hardware and data.
%
% But I've decided to start posting more detailed information here about the
% performance improvements.  I have more flexibility (and room!) here than we
% have with the release notes.
%
% Today I'll tackle 
% <http://www.mathworks.com/access/helpdesk/help/toolbox/images/index.html?/access/helpdesk/help/toolbox/images/imreconstruct.html 
% |imreconstruct|>, which performs morphological
% reconstruction.  Reconstruction is a very useful operation that I've written
% about here before.  For example, see my 
% <http://blogs.mathworks.com/steve/2008/07/14/opening-by-reconstruction/ 
% post from last year on opening by reconstruction>.  Several other Image Processing
% Toolbox functions call |imreconstruct|, including |imclearborder|, |imfill|,
% |imhmax|, |imhmin|, |imextendedmax|, |imextendedmin|, and |imimposemin|. 
%
% Let me use the 
% <http://blogs.mathworks.com/steve/2008/07/14/opening-by-reconstruction/  
% opening by reconstruction example> as a benchmark case.

url = 'http://blogs.mathworks.com/images/steve/2008/book_text.png';
text = imread(url);
imshow(text, 'InitialMagnification', 25)
title('918-by-2018 image displayed at 25% magnification')

%%
% The example task was to find letters containing vertical strokes by eroding
% with a vertical structuring element and then performing reconstruction.

se = strel(ones(51, 1));
marker = imerode(text, se);
text2 = imreconstruct(marker, text);
imshow(text2, 'InitialMagnification', 25)
title('Output image displayed at 25% magnification')

%%
% So how long does that call to |imreconstruct| take in R2009b?  I'll use my
% function
% <http://www.mathworks.com/matlabcentral/fileexchange/18798-timeit-benchmarking-function 
% |timeit|>, which you can download from the MATLAB Central File Exchange.

timeit(@() imreconstruct(marker, text))

%%
% That time is about 45 times faster than the same operation performed in
% R2009a.  Note that I'm running on two-core computer; the improved
% |imreconstruct| is multithreaded, so the performance improvement would be
% greater on a four-core computer, for example.
%
% Now let's time gray-scale reconstruction.  I'll make a 1024-by-1024 test
% image and compute a marker image by subtraction.  This kind of operation is
% often used to suppress small peaks in an image.

I = repmat(imread('rice.png'), 4, 4);
marker = I - 20;
timeit(@() imreconstruct(marker, I))

%%
% This time is about 30 times faster than R2009a, again running on my two-core
% laptop.
%
% Now for some key caveats you should know.  For now, the performance
% improvements described here only work for 2-D inputs that are uint8, uint16,
% or single, and only when the specified connectivity is 4 or 8.  We'll be
% working in the future to extend the speed improvements to other inputs.


##### SOURCE END ##### b2a3075faf7d470d90cb0c77ce2782fa
--><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/goLR2XpBknQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/10/19/faster-imreconstruct-in-r2009b/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/10/19/faster-imreconstruct-in-r2009b/</feedburner:origLink></item>
		<item>
		<title>Friday links</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/By5RSleLraY/</link>
		<comments>http://blogs.mathworks.com/steve/2009/10/16/friday-links-2/#comments</comments>
		<pubDate>Fri, 16 Oct 2009 15:16:18 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/10/16/friday-links-2/</guid>
		<description><![CDATA[
	Contour tracing - tutorial and algorithms


	List of computer vision research groups worldwide


	Camera Calibration Toolbox for MATLAB


	Daimler Pedestrian Benchmarks - for detection and classification


	The Berkeley Segmentation Dataset and Benchmark

]]></description>
			<content:encoded><![CDATA[<ul>
	<li><a href="http://www.imageprocessingplace.com/downloads_V3/root_downloads/tutorials/contour_tracing_Abeer_George_Ghuneim/index.html">Contour tracing - tutorial and algorithms</a></li>


	<li><a href="http://peipa.essex.ac.uk/info/groups.html">List of computer vision research groups worldwide</a></li>


	<li><a href="http://www.vision.caltech.edu/bouguetj/calib_doc/">Camera Calibration Toolbox for MATLAB</a></li>


	<li><a href="http://www.science.uva.nl/research/isla/downloads/pedestrians/index.html">Daimler Pedestrian Benchmarks - for detection and classification</a></li>


	<li><a href="http://www.eecs.berkeley.edu/Research/Projects/CS/vision/bsds/">The Berkeley Segmentation Dataset and Benchmark</a></li>

</ul><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/By5RSleLraY" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/10/16/friday-links-2/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/10/16/friday-links-2/</feedburner:origLink></item>
		<item>
		<title>MATLAB Virtual Conference - “the high point of geekism this year”</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/PR9KaIxmyIU/</link>
		<comments>http://blogs.mathworks.com/steve/2009/10/15/matlab-virtual-conference-the-high-point-of-geekism-this-year/#comments</comments>
		<pubDate>Thu, 15 Oct 2009 17:02:42 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/10/15/matlab-virtual-conference-the-high-point-of-geekism-this-year/</guid>
		<description><![CDATA[
I spent all of yesterday interacting with visitors to the MATLAB Virtual Conference. It was great fun! A blogger wrote that it was the "high point of geekism and nerdity of this year." (I think that was intended to be a compliment!)



It's not too late to hear the presentations. You can still visit the conference [...]]]></description>
			<content:encoded><![CDATA[<p>
I spent all of yesterday interacting with visitors to the MATLAB Virtual Conference. It was great fun! A <a href="http://mindsync.wordpress.com/2009/10/14/matlab-virtual-conference/">blogger</a> wrote that it was the "high point of geekism and nerdity of this year." (I think that was intended to be a compliment!)
</p>

<p>
It's not too late to hear the presentations. You can still <a href="http://events.unisfair.com/rt/matlab~virtualconf?code=hp-listing">visit the conference link</a> and listen to the talks there, or you can download them as podcasts.
</p>

<p>
I started out early in the morning in the Image and Video Processing booth, participating in the group chat there. When it got busy it was a bit challenging to follow all the conversational threads, but I think most people got their questions answered, and I came away with a lot of good product feedback.
</p>

<p>
Then I went over to hear Tom Kush and Roy Lurie give their "MATLAB Universe" keynote address. If you want to hear about the world-wide impact of MATLAB and get some insight into where we think MATLAB is going, check out this talk. (I didn't get a chance to listen to the other talks yesterday, but I will later.)
</p>

<p>
The experience reminded me of some of the MATLAB user conferences in the 1990s. One of the only times I've ever heard company president <a href="http://www.mathworks.com/company/aboutus/founders/jacklittle.html">Jack Little</a> tell a joke was during his keynote address at the 1995 user conference in Cambridge, Massachusetts. We had been working for several years on MATLAB 5, which was going to be a huge release. Conference attendees had been promised a preview. So at the opening of the conference, in an enormous ballroom, Jack fired up the development build of MATLAB 5 on the big screen and started to talk about all the exciting new features to come. He said there would be a few changes that might take some getting used to. (We developers were sitting on the back row, holding our breath.) Jack explained that we had decided to adopt RPN (<a href="http://en.wikipedia.org/wiki/Reverse_Polish_notation">Reverse Polish Notation</a>, popular in HP engineering calculators such as my beloved <a href="http://en.wikipedia.org/wiki/HP-15C">HP 15C</a>) in MATLAB. He proceeded to type something like:
</p>

<pre>
>> 5 3 +
</pre>

<p>
There was a massive collective gasp! from the audience as we about fell off our chairs in the back trying not to laugh out loud.
</p>

<p>
To any reader who was there (and is still recovering), I can only say, "We're sorry!"  ;-)
</p>

<p>
OK, back to the present. Later in the day I gave a talk on MATLAB array indexing techniques that are useful for image processing, borrowing heavily from material I <a href="http://blogs.mathworks.com/steve/category/indexing/">originally posted here on the blog</a>. I was afraid the material would be too narrowly focused, but the audience stayed with me to the end and then asked a bunch of great questions about my last topic, <a href="http://blogs.mathworks.com/steve/2008/02/25/neighbor-indexing-2/">neighbor indexing</a>, which was pretty advanced.
</p>

<p>
For the first five minutes of the talk (which I recorded a couple of weeks ago), I was in a rapidly increasing panic, because a 2-second echo was making the audio completely unintelligible! I bolted out of my office to find someone to help. Kevin calmed me down and helped me figure out that I had a second, forgotten, browser window open to the talk, and the echo was coming there. Boy did I feel silly. Thanks, Kevin!
</p>

<p>
Readers, I have two questions for you. First, did you attend any of the original MATLAB user conferences in the 90s? Any favorite memories to share?
</p>

<p>
Second, did you attend the virtual conference yesterday? What did you think? If we do it again, what can we do better next time?
</p>

<p>
Thanks for taking the time to give us your feedback.
</p>
<img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/PR9KaIxmyIU" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/10/15/matlab-virtual-conference-the-high-point-of-geekism-this-year/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/10/15/matlab-virtual-conference-the-high-point-of-geekism-this-year/</feedburner:origLink></item>
		<item>
		<title>Deploying Image Processing Toolbox apps in R2009b - we goofed</title>
		<link>http://feedproxy.google.com/~r/SteveOnImageProcessing/~3/b1JAZEKBwyQ/</link>
		<comments>http://blogs.mathworks.com/steve/2009/10/12/deploying-image-processing-toolbox-apps-in-r2009b-we-goofed/#comments</comments>
		<pubDate>Mon, 12 Oct 2009 07:00:38 +0000</pubDate>
		<dc:creator>Steve</dc:creator>
		
		<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://blogs.mathworks.com/steve/2009/10/12/deploying-image-processing-toolbox-apps-in-r2009b-we-goofed/</guid>
		<description><![CDATA[
Ack!



We discovered recently that we broke application deployment when using the MATLAB Compiler with Image Processing Toolbox functions in R2009b. The problem happens only on Windows and is caused by some missing shared libraries in the deployed application.



If you use the R2009b MATLAB Compiler on Windows with the Image Processing Toolbox, please see our published [...]]]></description>
			<content:encoded><![CDATA[<p>
Ack!
</p>

<p>
We discovered recently that we broke application deployment when using the <a href="http://www.mathworks.com/products/compiler/">MATLAB Compiler</a> with Image Processing Toolbox functions in R2009b. The problem happens only on Windows and is caused by some missing shared libraries in the deployed application.
</p>

<p>
If you use the R2009b MATLAB Compiler on Windows with the Image Processing Toolbox, please see our <a href="http://www.mathworks.com/support/bugreports/581700">published bug report</a> for a workaround. (Note: there is <strong>no need</strong> to apply this workaround to earlier releases.)
</p>

<p>
We are reviewing our procedures to try to make sure something like this doesn't happen again.
</p><img src="http://feeds.feedburner.com/~r/SteveOnImageProcessing/~4/b1JAZEKBwyQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://blogs.mathworks.com/steve/2009/10/12/deploying-image-processing-toolbox-apps-in-r2009b-we-goofed/feed/</wfw:commentRss>
		<feedburner:origLink>http://blogs.mathworks.com/steve/2009/10/12/deploying-image-processing-toolbox-apps-in-r2009b-we-goofed/</feedburner:origLink></item>
	</channel>
</rss>
