<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>code-spot &#187; Image Processing</title>
	<atom:link href="http://code-spot.co.za/category/image-processing/feed/" rel="self" type="application/rss+xml" />
	<link>http://code-spot.co.za</link>
	<description>a programming blog</description>
	<lastBuildDate>Sun, 27 Feb 2011 07:18:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<item>
		<title>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</title>
		<link>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/</link>
		<comments>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/#comments</comments>
		<pubDate>Sun, 23 Jan 2011 22:30:49 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[implicit queue algorithm]]></category>
		<category><![CDATA[max-queue algorithm]]></category>
		<category><![CDATA[maximum filter]]></category>
		<category><![CDATA[minimum filter]]></category>
		<category><![CDATA[monotonic wedge algorithm]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1100</guid>
		<description><![CDATA[A while back I needed to implement fast minimum and maximum filters for images. I devised (what I thought was) a clever approximation scheme where the execution time is not dependent on the window size of the filter. But the method had some issues, and I looked at some other algorithms. In retrospect, the method I [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='Permanent Link: 5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1101" title="minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2011/01/minmax.png" alt="" width="491" height="321" /></p>
<p>A while back I needed to implement fast minimum and maximum filters for images. I devised (what I thought was) a <a href="http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/">clever approximation scheme</a> where the execution time is not dependent on the window size of the filter. But the method had some issues, and I looked at some other algorithms. In retrospect, the method I used seems foolish. At the time, I did not realise the obvious: a 1D filter could be applied to first the rows, and then the columns of an image, which makes the slow algorithm faster, or allows you to use one of the many published fast 1D algorithms.</p>
<p>I wanted to write down my gained knowledge, and started to work on a blog post. But soon it became quite long, so I decided to put it into a PDF document instead. You can download it below.</p>
<p><span id="more-1100"></span>The document is somewhat weird: it is very detailed for a &#8220;simple&#8221; image algorithm (it is more than 50 pages!). It does have several tips that applies to implementation of other image processing algorithms. It also has, what I believe to be, a very clear description of the Monotonic Wedge Algorithm, with code that reflects the explanation in text closely. (I had trouble understanding the algorithm from the original journal publication. And the authors provide code that was even further optimised and thus less clear to follow).</p>
<p>I intended to give some performance analysis and results, but other activities has robbed me of any free time. Perhaps later.</p>
<p>Also, the code has been edited for readability, and hence, might contain typos that were introduced in the process. If you spot any, please let me know.</p>
<h2>Download</h2>
<p><a href="http://www.code-spot.co.za/downloads/image/minmax_filters.pdf">minmax_filters.pdf (230 KB)</a></p>
<h2>Table of Contents</h2>
<blockquote>
<div id="_mcePaste">1 The Problem</div>
<div id="_mcePaste">2 Exact Algorithms</div>
<div id="_mcePaste">2.1 The Naive Algorithm</div>
<div id="_mcePaste">2.2 The Max-Queue</div>
<div id="_mcePaste">2.3 Implicit Queue Algorithm</div>
<div id="_mcePaste">2.4 The Monotonic Wedge Algorithm</div>
<div id="_mcePaste">3 Approximate Algorithms</div>
<div id="_mcePaste">3.1 The Power Mean Approximation</div>
<div id="_mcePaste">3.2 The Power Mean Variant Algorithm</div>
<div id="_mcePaste">3.3 The Contra-Harmonic Mean Approximation</div>
<div id="_mcePaste">4 Other Algorithm Concepts</div>
<div id="_mcePaste">4.1 Separation</div>
<div id="_mcePaste">4.2 Implementing Minimum Filters</div>
<div id="_mcePaste">4.3 Windows with Even Diameters</div>
<div id="_mcePaste">4.4 Filtering a Region of Interest</div>
<div id="_mcePaste">4.5 Maximum and Minimum Filters for Binary Images</div>
<div id="_mcePaste">A Image Containers</div>
<div id="_mcePaste">A.1 Image Class Interface</div>
<div id="_mcePaste">A.2 Image Loops</div>
<div id="_mcePaste">A.3 Image Iterators</div>
<div id="_mcePaste">A.4 Image Access Modifiers</div>
<div id="_mcePaste">B Fixed-width Deques</div>
<div id="_mcePaste">C Max-queues</div>
<div id="_mcePaste">D Summed Area Tables</div>
<div id="_mcePaste">D.1 Calculating a SAT</div>
<div id="_mcePaste">D.2 Finding a Sum from a SAT</div>
<div id="_mcePaste">D.3 Checking for Overflow 50</div>
<div id="_mcePaste">D.4 Large SATs 53</div>
</blockquote>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='Permanent Link: 5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Region Quadtrees in C++</title>
		<link>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/</link>
		<comments>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/#comments</comments>
		<pubDate>Tue, 15 Jun 2010 11:14:14 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[image partitioning]]></category>
		<category><![CDATA[quadtree]]></category>
		<category><![CDATA[quadtrees]]></category>
		<category><![CDATA[spatial partitioning]]></category>
		<category><![CDATA[sum]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=983</guid>
		<description><![CDATA[(Original image by GoAwayStupidAI). Below are four C++ implementations of the region quadtree (the kind used for image compression, for example). The different implementations were made in an attempt to optimise construction of quadtrees. (For a tutorial on implementing region quadtrees, see Issue 26 [6.39 MB zip] of Dev.Mag). NaiveQuadtree is the straightforward implementation. AreaSumTableQuadtree [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline; border: 0px;" title="quadtree" src="http://code-spot.co.za/blog/wp-content/uploads/2010/06/quadtree.png" border="0" alt="quadtree" width="491" height="375" /></p>
<p>(<a href="http://www.flickr.com/photos/goawaystupidai/3106598088/">Original image</a> by <a href="http://www.flickr.com/photos/goawaystupidai/">GoAwayStupidAI</a>).</p>
<p>Below are four C++ implementations of the <a href="http://www.voronoi.com/wiki/index.php?title=Quadtree">region quadtree</a> (the kind used for image compression, for example). The different implementations were made in an attempt to optimise <em>construction </em>of quadtrees. (For a tutorial on implementing region quadtrees, see <a href="http://www.devmag.org.za/uploads/DevMag_Issue26.zip" class="broken_link">Issue 26</a> [6.39 MB zip] of <a href="http://devmag.org.za/">Dev.Mag</a>).</p>
<ul>
<li><strong>NaiveQuadtree </strong>is the straightforward implementation.</li>
<li><strong>AreaSumTableQuadtree </strong>uses a <a href="http://en.wikipedia.org/wiki/Summed_area_table">summed area table</a> to perform fast calculations of the mean and variance of regions in the data grid.</li>
<li><strong>AugmentedAreaSumTableQuadtree </strong>is the same, except that the area sum table has an extra row and column of zeros to prevents if-then logic that slows it down and makes it tricky to understand.</li>
<li><strong>SimpleQuadtree </strong>is the same as AugmentedAreaSumTableQuadtree , except that no distinction is made (at a class level) between different node types.</li>
</ul>
<p><span id="more-983"></span>The interfaces of all quadtrees are the same, but I did not want to extend from a base class. (Instead, a compile time check is performed on the classes, using <a href="http://www.boost.org/doc/libs/1_43_0/libs/concept_check/concept_check.htm">boost concepts</a>).</p>
<p>The results of the performance (on my machine!) of the trees are as follows:</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td style="text-align: left;" width="100" valign="top">(milliseconds)</td>
<td style="text-align: right;" width="100" valign="top"><strong>N</strong></td>
<td style="text-align: right;" width="100" valign="top"><strong>S</strong></td>
<td style="text-align: right;" width="100" valign="top"><strong>AST</strong></td>
<td style="text-align: right;" width="100" valign="top"><strong>AAST</strong></td>
</tr>
<tr>
<td style="text-align: right;" width="100" valign="top"></td>
<td style="text-align: right;" width="100" valign="top">3</td>
<td style="text-align: right;" width="100" valign="top">4</td>
<td style="text-align: right;" width="100" valign="top">4</td>
<td style="text-align: right;" width="100" valign="top">3</td>
</tr>
<tr>
<td width="100" valign="top"><strong>64×64</strong></td>
<td style="text-align: right;" width="100" valign="top">14</td>
<td style="text-align: right;" width="100" valign="top">14</td>
<td style="text-align: right;" width="100" valign="top">14</td>
<td style="text-align: right;" width="100" valign="top">13</td>
</tr>
<tr>
<td width="100" valign="top"><strong>128×128</strong></td>
<td style="text-align: right;" width="100" valign="top">55</td>
<td style="text-align: right;" width="100" valign="top">52</td>
<td style="text-align: right;" width="100" valign="top">55</td>
<td style="text-align: right;" width="100" valign="top">52</td>
</tr>
<tr>
<td width="100" valign="top"><strong>256×256</strong></td>
<td style="text-align: right;" width="100" valign="top">229</td>
<td style="text-align: right;" width="100" valign="top">233</td>
<td style="text-align: right;" width="100" valign="top">218</td>
<td style="text-align: right;" width="100" valign="top">214</td>
</tr>
<tr>
<td width="100" valign="top"><strong>512×512</strong></td>
<td style="text-align: right;" width="100" valign="top">950</td>
<td style="text-align: right;" width="100" valign="top">1036</td>
<td style="text-align: right;" width="100" valign="top">937</td>
<td style="text-align: right;" width="100" valign="top">922</td>
</tr>
<tr>
<td width="100" valign="top"><strong>1024×1024</strong></td>
<td style="text-align: right;" width="100" valign="top">4064</td>
<td style="text-align: right;" width="100" valign="top">4459</td>
<td style="text-align: right;" width="100" valign="top">5396</td>
<td style="text-align: right;" width="100" valign="top">3891</td>
</tr>
</tbody>
</table>
<p>As it turns out, the different implementations do not differ significantly. Constructing the nodes takes long, and not so much the calculations necessary to determine whether a node should split or not, and what data should be in the node. Had I profiled properly before I started I would not have gone through this exercise…</p>
<p>Between these four implementations, the NaiveQuadtree is the one I recommend; I left in the other implementations for anyone interested.</p>
<p>The one good thing that came from this experiment is that I found out that using a zero-augmented summed area table can increase performance quite a bit. This is useful for <a href="http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/">max-filters</a> and other algorithms that use these tables.</p>
<p>You can download the source code:</p>
<p><a href="http://www.code-spot.co.za/downloads/cpp/Quadtree.zip">Quadtree.zip</a> (44 KB, Visual Studio).</p>
<p>(It requires the <a href="http://www.boost.org/users/download/">boost library</a> for concept checking, but nothing else. Everything will still work if you remove all references to the boost library. If you already have boost, just hook up to the include path in Visual Studio).</p>
<p>&#8230;or read the <a href="http://www.code-spot.co.za/downloads/cpp/quadtrees/html/index.html">online documentation</a>.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Catching Common Image Processing Programming Errors with Generic Unit Tests</title>
		<link>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/</link>
		<comments>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/#comments</comments>
		<pubDate>Wed, 12 May 2010 13:40:30 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[unit testing]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=936</guid>
		<description><![CDATA[When implementing image algorithms, I am prone to make these mistakes: swapping x and y; working on the wrong channel; making off-by-one errors, especially in window algorithms; making division-by-zero errors; handling borders incorrectly; and handling non-power-of-two sized images incorrectly. Since these types of errors are prevalent in many image-processing algorithms, it would be useful to [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-947" title="crash test dummy" src="http://code-spot.co.za/blog/wp-content/uploads/2010/05/dummy1.png" alt="crash test dummy" width="491" height="321" /></p>
<p>When implementing image algorithms, I am prone to make these mistakes:</p>
<ul>
<li>swapping x and y;</li>
<li>working on the wrong channel;</li>
<li>making off-by-one errors, especially in window algorithms;</li>
<li>making division-by-zero errors;</li>
<li>handling borders incorrectly; and</li>
<li>handling non-power-of-two sized images incorrectly.</li>
</ul>
<p>Since these types of errors are prevalent in many image-processing algorithms, it would be useful to develop, once and for all, general tests that will catch these errors quickly for <em>any</em> algorithm.</p>
<p>This post is about such tests.</p>
<p><span id="more-936"></span></p>
<h2>The General Idea</h2>
<p>The general idea is to exploit the fact that many algorithms satisfy invariants such as these:</p>
<pre>some_transform(algorithm(image))
  == algorithm(some_transform(image))</pre>
<p>For example: a 3-by-3 box blur is invariant under a vertical flip:</p>
<pre>box_blur3x3(flip_vertical(image))
  == flip_vertical(box_blur3x3 (image))</pre>
<p>It does not matter whether we apply the flip before or after applying the box filter—the result should be the same.</p>
<p>What kind of errors can the above test expose? Since it checks whether the algorithm (not the image) is vertically symmetric, the test can catch certain off-by-one errors along the vertical axis. Here is an example of a faulty implementation of the blur algorithm. Here the function <code>sum</code> adds all the pixel values in the rectangle x0..x1 – 1 and y0..y1 – 1.</p>
<pre>//C-like pseudo-code
Image &amp; box_filter3x3(Image &amp; image)
{
  forXY(image, x, y)
  {
    x0, y0 = max(0, x – 1), max(0, y – 1)
    x1, y1 = min(x + 1, image.width), min(y + 1, image.height)
    result = sum(image, x0, x1, y0, y1) / ((x1 – x0) * (y1 – y0));
  }

  image = result;
  return image;
}</pre>
<p>Can you spot the error? The actual window used is only 2 by 2. But how does the test catch this error? To see why the test will fail, notice the difference in windows for the top-left and bottom-left pixels:</p>
<p>Top Left:</p>
<pre>x0, y0 == 0, 0
x1, y1 == 1, 1</pre>
<p>Bottom Left</p>
<pre>x0, y0 == width – 2, height – 2
x1, y1 == width , height</pre>
<p>As you can see, the two windows have different sizes! The bottom-left pixel window is 1 by 1, but the top left pixel is 2 by 2. Thus flipping the image before and after applying the box-blur gives different results.</p>
<p>The correct algorithm is</p>
<pre>//C-like pseudo-code
Image &amp; box_filter3x3(Image &amp; image)
{
  forXY(image, x, y)
  {
    x0, y0 = max(0, x – 1), max(0, y – 1)
    x1, y1 = min(x + 2, image.width), min(y + 2, image.height)
    result = sum(image, x0, x1, y0, y1) /
      ((x1 – x0) * (y1 – y0));
  }

  image = result;

  return Image;
}</pre>
<p>Now the windows for the top and bottom left pixels are:</p>
<pre>x0, y0 == 0, 0
x1, y1 == 2, 2</pre>
<p>Bottom Left</p>
<pre>x0, y0 == width – 2, height – 2
x1, y1 == width , height</pre>
<p>We can see the window sizes are now the same.</p>
<h2>Transforms</h2>
<p>Here is a list of suggested transforms and the types of errors they can catch:</p>
<table border="0" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td width="140" valign="top"><code>flipVertical<br />
</code><code>flipHorizontal</code></td>
<td width="340" valign="top">Off-by-one errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>flipDiagonal</code></td>
<td width="340" valign="top">Swapping x and y.</td>
</tr>
<tr>
<td width="140" valign="top"><code>rotateChannels</code></td>
<td width="340" valign="top">Working on the wrong channel.</td>
</tr>
<tr>
<td width="140" valign="top"><code>invert</code></td>
<td width="340" valign="top">Calculation mistakes, certain kinds of division-by-zero. errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>scaleIntensity</code></td>
<td width="340" valign="top">Calculation mistakes.</td>
</tr>
<tr>
<td width="140" valign="top"><code>adjustGamma</code></td>
<td width="340" valign="top">Certain kinds of statistical ordering errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>crop</code></td>
<td width="340" valign="top">Certain kind of incorrect border calculations, certain power-of-two errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>translateVertival<br />
</code><code>translateHorizontal</code></td>
<td width="340" valign="top">Certain kinds of incorrect border calculations, off-by-one errors.</td>
</tr>
<tr>
<td width="140" valign="top"><code>desaturate</code></td>
<td width="340" valign="top">Certain channel processing errors.</td>
</tr>
</tbody>
</table>
<p>Many algorithms should (in theory) also be invariant under scaling. However, because of the complexity involved in interpolation and sampling, I do not recommend using scaling for testing. It is quite difficult to determine under some interpolation or sampling scheme whether an algorithm should in fact be (exactly) invariant or not under scaling. This of course also applies to other transforms that rely on sampling or interpolation.</p>
<p>You will probably also select transforms that are more specific to the algorithms you are implementing. Keep these as simple as possible—not only to avoid implementation errors, but also to avoid subtle misconceptions: it must be easy to see (or well established) that a certain algorithm is invariant under a transform. Test your own transform functions aggressively.</p>
<h2>Generic Solutions</h2>
<p>Writing test code for each transform is easy, but tedious (and hence error prone). Here I show how a generic test can be implemented using C++ macros or functional programming. The generic test can be used to test whether any algorithm is invariant under a given transform.</p>
<h3>Macros Implementation</h3>
<p>Probably the easiest way to implement a general test-function in C++ is to implement it as a macro. Here is how this looks:</p>
<pre>//C++
#define TEST_TRANSFORM_INVARIANCE(image, transform, command) \
  do { \
    Image image; \
    make_test_image(image); \
    \
    Image original_image(image); \
    command; \
    \
    Image image1(image); \
    transform(image1); \
    \
    image = original_image; \
    transform(image); \
    command; \
    \
    if (image != image1) \
      report_useful_failure_message(...); \
  } while(0)</pre>
<p>We can now use this macro like this:</p>
<pre>TEST_TRANSFORM_INVARIANCE (image, flipVertical, my_algorithm(image));</pre>
<p>The nice thing about the macro approach is how easy functions that take any number of parameters can be tested:</p>
<pre>TEST_TRANSFORM_INVARIANCE (image, flipVertical, my_algorithm(image, 10, 20));</pre>
<p>Notice that the first parameter is a <em>variable name</em>. The macro declares this variable, and the user can use it in the command parameter to pass the image to the algorithm.</p>
<h3>Functional Programming Implementation</h3>
<p>If macros are not available, or using them is not desirable, you can still use a generic approach. Unfortunately, we need to define functions with a consistent argument list for each test we want to perform, which means we might need to write more code in some languages.</p>
<p>The general test function can be defined as follows in C++:</p>
<pre>//C++
test_transform_inavriance(
  Image &amp; (* function)(Image &amp;),
  Image &amp; (* transform)(Image &amp;))
{
  Image image;
  make_test_image(image);

  Image original_image(image);
  function(image);

  Image image1(image);
  transform(image1);

  image = original_image;
  transform(image);
  function(image);

  if (image != image1)
    report_useful_failure_message(...);
}</pre>
<p>To use it with a single argument function, we simply call it like this:</p>
<pre>test_transform_inavriance(flip_vertical, my_algorithm);</pre>
<p>To use it with a function that takes more than one parameter, we need to define a function to call the extra parameters:</p>
<pre>// C++
Image &amp; test_my_algorithm_wrapper(Image &amp; image)
{
  my_algorithm(image, 10, 20);
}
...
test_transform_inavriance(flip_vertical, my_algorithm_wrapper);</pre>
<p>In languages that support closures, you can wrap functions more cleanly so that you do not need to define a function for each test command. For example, in Python:</p>
<pre># Python
def wrap(fn, args):
  def wrapper(image):
    fn(image, *args)
  return fn
...
test_transform_inavriance(flip_vertical, wrap(my_algorithm, 10, 20));</pre>
<h2>Test Bundles</h2>
<p>Both the macro and functional programming approaches allow you to combine tests of different transforms in convenient functions:</p>
<pre>// C++
#define TEST_ALL(image, command)\
  do { \
    TEST_TRANSFORM_INVARIANCE (image, flip_vertical, command); \
    TEST_TRANSFORM_INVARIANCE (image, flip_horizontal, command); \
    ...
  } while(0)</pre>
<pre>// C++
void test_all(Image &amp; (* fn)(Image &amp;))
{
  test_transform_inavriance(flip_vertical, function);
  test_transform_inavriance(flip_ horizontal, function);
  ...
}</pre>
<h2>Test Images</h2>
<p>It is important that your images do not destroy the very asymmetry that you are trying to expose. For instance, if we ran the test at the very beginning of this post with an all-zero image, the test will have passed. The image should be asymmetric under the transform we are using, that is, the following must hold:</p>
<pre>transform(image) != image</pre>
<p>For different transforms, this means different things. For example, for flip_diagonal, the image must not be square, for inverse, the image must not be the constant grayscale image 0.5.</p>
<p>It is useful to build an extra test into our test macro or function, to make sure that we do not inadvertently break this requirement. Here is the modified macro:</p>
<pre>// C++
#define TEST_TRANSFORM_INVARIANCE(image, transform, command)\
  do { \
    Image image; \
    make_test_image(image); \
    \
    Image original_image(image); \
    transform(image); \
    \
    if(image == original_image) \
      report_unsuitable_test_image(...); \
    \
    image = original_image; \
    command; \
    \
    Image image1(image); \
    transform(image1); \
    \
    image = original_image; \
    transform(image); \
    command; \
    \
    if (image != image1) \
      report_useful_failure_message(...); \
  } while(0)</pre>
<p>For many algorithms, using an image of noise (independent for each channel) works well. Make sure the image have unequal dimensions that are prime numbers (for example, 11 and 13). Using prime numbers ensures that the two dimensions will not have any common divisors, which makes certain kind of tests for recursive algorithms (such as quad-tree compression) more robust.</p>
<h2>Reporting Failures</h2>
<p>In the example implementation, we have the line</p>
<pre>if (image != image1) report_useful_failure_message(...);</pre>
<p>This is a somewhat simplistic scheme. What is a useful failure message? Of course, the message must report the test that failed. But it should also give information about how the test failed:</p>
<ul>
<li>whether it was a mismatch of the number of channels, image dimensions, or pixel values;</li>
<li>the number of channels and image dimensions;</li>
<li>the number of pixels for which the test failed; and</li>
<li>the first pixel location where the test failed, and the expected and actual pixel values.</li>
</ul>
<p>These bits of information can help us hunt down the cause. For example, if the test data is an 11-by-13 image, and the test fails for 13 pixels, the error is most likely a border problem caused by an off-by-one error. If the first pixels that fails is 0, 0, and the test fails for (almost) all pixels, and the pixel values differ only by sign, we can guess that there is some sign error made that affects the entire image.</p>
<p>The actual test will thus be a bit more complicated, delegating to a function such as this:</p>
<pre>test_image_equality(
  Image &amp; image1,
  Image image 2,
  FailureInfo &amp; info)
{
  info.has_failed = false;
  info.failed_pixels_count = 0;
  info.dimensions_image1 = image1.dimensions;
  info.dimensions_image2 = image2.dimensions;
  info.channels_image1 = image1.channels
  info.channels_image2 = image2.channels

  if(image1.channels != image2.channels)
  {
     info.has_failed = true;
     info.failure_type = CHANNEL_MISMATCH;
     return;
  }

  if(image1.dimensions != image2.dimensions)
  {
    info.has_failed = true;
    info.failure_type = DIMENSION_MISMATCH;
    return;
  }

  forXY(image, x, y)
  {
    if(abs(image1(x, y) - image2(x, y)) &lt; THRESHOLD)
    {
      if (!info.has_failed)
      {
        info.has_failed = true;
        info.failure_type = VALUE_MISMATCH;
        info.first_failed_x = x;
        info.first_failed_y = y;
        info_first_failed_image1 = image1(x,y);
        info_first_failed_image2 = image2(x,y);
      }

      info.failed_pixels_count++;
    }
  }
}</pre>
<p>In the test macro or function, we call the function like this:</p>
<pre>...
FailureInfo info; \
test_image_equality(image, image1, info); \
if (info.has_failed) report_failure(info); \
...</pre>
<h2>Using Third-Party Image Libraries</h2>
<p>It is important that you understand the transforms you use for testing very well. It is therefore a good idea to use you own transforms, and not those of a library. This way, unknown design choices in the library cannot bite you. Many image libraries do not for example specify how they handle borders, division by zero, rounding, etc. These details are often not important when using the algorithms in a task—but they can make a test fail (or succeed) when it should not.</p>
<p>The same danger exists when you use third party algorithms as building blocks for your own. In this case testing your code will be harder. As a starting point, consider testing whether third party algorithms satisfy the invariants you expect to hold. If they do not, you may need to modify your test code to accommodate for the discrepancy. If they do, you can be a little more confident that your tests will be reliable.</p>
<p>(Yes, it is not normally recommended to test other people&#8217;s code with unit tests. However, this is a once-off test to make sure that your own tests are reliable, and since it is so easy to implement (since you already have the test macro / function and transforms), I do not see the harm. Just keep the third-party library test separate from your own.)</p>
<h2>Defining Correctness—When are two images equal?</h2>
<p>Correctness of an image algorithm is a subtle issue, mostly because the discrete, quantized, finite model of image computation is inherently an approximation of the “real” thing. The question is too broad to tackle here (and frankly, I do not have enough knowledge to do it), so I will focus on aspects that are specifically relevant to this kind of testing.</p>
<p>Let us start with an example of an essentially correct algorithm that fails a test that we expect that it should not:</p>
<pre>// C++
Image &amp; threshold(Image &amp; image)
{
  forXY(image, x, y)
    image(x, y) = (image(x, y) &lt;= 0.5f) ? 0 : 1;

  return image;
}</pre>
<p>We expect this simple algorithm to be invariant under the inverse transform. However, it is not. Consider a pixel value of 0.5: the inverse of this is 0.5. So both the pixel and its inverse will map to zero, and hence the following will not be true:</p>
<pre>inverse(threshold(image)) == threshold(inverse(image)) //not true
inverse(threshold(0.5f)) == inverse(0) == 1 //left side
threshold(inverse(0.5f)) == threshold(0.5f) == 0 //right side</pre>
<p>It looks like the problem is easily solved by changing the algorithm:</p>
<pre>// C++
Image &amp; threshold(Image ℑ)
{
  forXY(image, x, y)
    image(x, y) = (image(x, y) &lt; 0.5f) ? 0 : 1;

  return image;
}</pre>
<p>But, for floating point numbers on a machine, there is another number 0.5 – epsilon such that the following algorithm is equivalent to the one above:</p>
<pre>// C++
Image &amp; threshold(Image &amp; image)
{
  forXY(image, x, y)
    image(x, y) = (image(x, y) &lt;= 0.5f - epsilon) ? 0 : 1;

  return image;
}</pre>
<p>But for this algorithm our invariant does not hold for a pixel with the value 0.5 – epsilon! Since the last two algorithms are equivalent, it means the modified algorithm is also not correct in this strict sense. In fact, it is not possible to implement an algorithm that is correct in this sense (using floating-point numbers).</p>
<p>But we feel that any of the above implementation <em>is</em> correct, and hence our test is wrong. So how do we change it, and should we?</p>
<p>We can change one (or more) of three things:</p>
<ul>
<li>the test data</li>
<li>the test transform</li>
<li>how we test for equality in images</li>
</ul>
<p>Because of the simplicity and general usefulness of both the transform and the test data, I feel it is best to leave these as is. That means we have to change the measure of equality. Since we use random data, we might want to use the “is probably equal” measure—that is, two images are equal if a certain percentage of pixels are equal (within some threshold). Since the likelihood of generating 0.5 is low, our test should pass. I do not like this idea for two reasons:</p>
<p>First, it is not generally useful. For example, another test might fail when the borders are not equal (a much larger number of pixels), even though we feel that it must not for some specific algorithm. We then need another equality measure to handle that case.</p>
<p>Second, it is bound to hide a class of errors where a small number of pixels are incorrectly processed, and we do not want that.</p>
<p>Instead, we would like some measure that is generally useful, but can be tweaked for the specific algorithm to overcome those cases where we expect the algorithm to fail.</p>
<p>One way to do this is to use equality masks: a simple bit array that says whether we are interested in that pixel or not. In this case, we need the mask to be constructed from the test data; here is how we do it:</p>
<pre>//C++
BitImage &amp; make_ignore_value_mask(
  BitImage &amp; mask,
  Image &amp; image,
  float value)
{
  forXY(image, x, y)
    mask = image(x, y) == 0.5f;
}</pre>
<p>We then change our macro to this:</p>
<pre>#define TEST_TRANSFORM_INVARIANCE (image, mask, transform, command, mask_command) \
  do { \
    Image image; \
    make_test_image(image); \
    \
    Image original_image(image); \
    transform(image); \
    \
    if(image == original_image)
      report_unsuitable_test_image(...); \
    \
    image = original_image; \
    command; \
    \
    Image image1(image); \
    transform(image1); \
    \
    image = original_image; \
    transform(image); \
    command; \
    \
    BitImage mask(image.width, image.height); \
    mask_command; \
    \
    if (mask * image != mask * image1)
      report_useful_failure_message(...); \
  } while(0)</pre>
<p>We call the macro like this:</p>
<p>TEST_TRANSFORM_INVARIANCE (image, mask, inverse, threshold(image), make_ignore_value_mask(mask, image, value));</p>
<p>The functional programming solutions are similarly modified:</p>
<pre>// C++
test_transform_inavriance(
  Image &amp; (* function)(Image &amp;),
  BitImage &amp; (*mask_creation_function) (BitImage &amp; mask, Image &amp; image),
  Image &amp; (* transform)(Image &amp;))
{
  Image image;
  make_test_image(image);

  Image original_image(image);

  if(image == original_image)
      report_unsuitable_test_image(...); 

  image = original_image;
  function(image);

  Image image1(image);
  transform(image1);

  image = original_image;
  transform(image);
  function(image);

  BitImage mask;
  mask_creation_function(mask, image);

  if (mask * image != mask * image1)
    report_useful_failure_message(...);
}</pre>
<p>We need a wrapping function to call our extra argument:</p>
<pre>BitImage &amp; void wrapped_ make_ignore_value_mask(
  BitImage &amp; mask,
  Image &amp; image)
{
  return make_ignore_value_mask(mask, image, 0,5f);
}</pre>
<p>Now we can call our test function like this:</p>
<pre>test_transform_inavriance(image, mask, inverse, threshold,
  wrapped_make_ignore mask(mask, image));</pre>
<p>In languages that support closures such as Python, we can again use the wrapping technique as before:</p>
<pre>test_transform_inavriance(image, mask, inverse, threshold,
  wrap(make_ignore mask(mask, image), 0.5))</pre>
<p>Here are a few suggestions for useful mask types:</p>
<table border="0" cellspacing="5" cellpadding="0">
<tbody>
<tr>
<td width="158" valign="top"><code>ignore_none</code></td>
<td width="340" valign="top">A constant array of 1s. Probably the one to be used with most algorithms.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_value</code><br />
<code>ignore_values</code></td>
<td width="340" valign="top">Ignores all the pixels in the test data that equal a given value or list of values.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_range</code></td>
<td width="340" valign="top">Ignores all the pixels in the test data that fall in the given range.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_out_of_range</code></td>
<td width="340" valign="top">Ignores all the pixels in the test data that fall outside a given range.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_rect</code></td>
<td width="340" valign="top">Ignores all the pixels inside a specified rectangle.</td>
</tr>
<tr>
<td width="158" valign="top"><code>ignore_border</code></td>
<td width="340" valign="top">Ignore all pixels in a boarder of specified width.</td>
</tr>
</tbody>
</table>
<p>Be careful for inadvertent ignore_all masks. For example, the ignore_border mask might be all zero when the border is thicker than half the smallest image dimension. It is a good idea to build in a test to check that the mask is not all-zero in the test macro or function.</p>
<p>Also watch out when transforms or algorithms change image dimensions—make sure the mask is constructed correctly.</p>
<p>We have now answered how we can change the test to pass for the thresholding example (and more generally); it remains to answer whether we should. My feeling is: only when you <em>have </em>to. Generally, I test without regard for such subtle issues. When a test fails, I carefully try to understand whether it is because the algorithm is fundamentally wrong, or whether it is just an obscure instance that makes the test fail. In the latter case, I will amend the test with the necessary masks.</p>
<p><b>Update</b>: Here is another example of how an invariance test can fail even when the algorithm is fundamentally correct. Consider a region quadtree compression scheme. Suppose we want to compress a 5&#038;times 5 image, and suppose the algorithm divides the image in four rectangles. Because 5 is odd, the rectangles will differ in size. The biggest rectangle should always be in the same spot, regardless of the reflection; thus the algorithm should fail when testing pixels along the center. We cannot really address this issue with masks. To me it is unclear how to handle this at all (and clearly, we do not want to limit our tests to powers-of-two images only).</p>
<h2>Warning: A False sense of Security</h2>
<p>When you have a large group of transforms to construct invariance checks from, you can easily test for a whole bunch of errors with just a few lines of code. If the tests pass, it is easy to think that the algorithm is correct. It may not be:</p>
<ul>
<li>Perhaps the test image is unsuitable. This may be by coincidence if the test image is random.</li>
<li>Any particular test does not catch all errors of a certain type.</li>
<li>All transforms do not cover the entire set of possible errors.</li>
</ul>
<p>A set of invariance tests does in general not prove the <em>correctness</em> of a particular algorithm. It merely exposes <em>certain kinds of errors</em>. Therefore, additional tests for correctness are necessary.</p>
<h2>Invariance Test Checklist / Summary</h2>
<p>The basic structure of the test macro / function is as follows:</p>
<ol>
<li>Create test data.</li>
<li>Calculate transform(algorithm(test_image)).</li>
<li>Calculate algorithm(transform(test_image)).</li>
<li>Compare these results and report any failures.</li>
</ol>
<p>Remember:</p>
<ul>
<li>Check that the test data is changed by the transform.</li>
<li>Use masks to cater for peripheral special cases where certain pixels, values, or regions in an image should be ignored for comparisons.</li>
<li>Check that your masks are not all zero (sanity check).</li>
<li>Report useful information when a test fails:
<ul>
<li>what kind of failure (dimension mismatch, channel mismatch, value mismatch);</li>
<li>in the case of value mismatch, the number of pixels that are mismatched and the values of the first pixels from each image that fail to match.</li>
</ul>
</li>
</ul>
<h2>More on Unit Testing for Image Processing</h2>
<ul>
<li><a href="http://blogs.mathworks.com/steve/2009/02/03/mtest-a-unit-test-harness-for-matlab-code/">MTEST &#8211; A unit test harness for MATLAB code</a></li>
<li><a href="http://aras-p.info/blog/2007/07/31/testing-graphics-code/">Testing Graphics Code</a></li>
</ul>
<h2>How do <em>You </em>Test Your Image Algorithms?</h2>
<p>Let me know in the comments <img src='http://code-spot.co.za/blog/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> </p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Permanent Link: Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple, Fast* Approximate Minimum / Maximum Filters</title>
		<link>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/</link>
		<comments>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/#comments</comments>
		<pubDate>Fri, 16 Apr 2010 14:13:05 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[algorithm]]></category>
		<category><![CDATA[dilation]]></category>
		<category><![CDATA[erosion]]></category>
		<category><![CDATA[filtering]]></category>
		<category><![CDATA[maximum filter]]></category>
		<category><![CDATA[minimum filter]]></category>
		<category><![CDATA[morphology]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=881</guid>
		<description><![CDATA[*Fast = not toooo slow… For the image restoration tool I had to implement min and max filters (also erosion and dilation—in this case with a square structuring element). Implementing these efficiently is not so easy. The naive approach is to simply check all the pixels in the window, and select the maximum or minimum value. This [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/' rel='bookmark' title='Permanent Link: 2D Minimum and Maximum Filters: Algorithms and Implementation Issues'>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</a></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Permanent Link: Region Quadtrees in C++'>Region Quadtrees in C++</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="display: inline; border: 0px initial initial;" title="minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/minmax.png" border="0" alt="minmax" width="491" height="321" /></p>
<p><em>*Fast = not toooo slow…</em></p>
<p>For the <a href="http://code-spot.co.za/2010/04/15/experimental-tool-for-removing-unwanted-artefacts-in-textures/">image restoration tool</a> I had to implement <a href="http://livedocs.adobe.com/en_US/Photoshop/10.0/help.html?content=WSfd1234e1c4b69f30ea53e41001031ab64-795d.html">min and max filters</a> (also <a href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/erode.htm">erosion</a> and <a href="http://homepages.inf.ed.ac.uk/rbf/HIPR2/dilate.htm">dilation</a>—in this case with a square <a href="http://en.wikipedia.org/wiki/Structuring_element">structuring element</a>). Implementing these efficiently is not so easy. The naive approach is to simply check all the pixels in the window, and select the maximum or minimum value. This algorithm&#8217;s run time is quadratic in the window width, which can be a bit slow for the bigger windows that I am interested in. There are some very efficient algorithms available, but they are quite complicated to implement properly (some require esoteric data structures, for example <a href="http://www.archipel.uqam.ca/309/1/webmaximinalgo.pdf">monotonic wedges</a> (PDF)), and many are not suitable for floating point images.</p>
<p>So I came up with this approximation scheme. It uses some expensive floating point operations, but its run time is <em>constant</em> in the window width.</p>
<p><span id="more-881"></span></p>
<p>The crux of the algorithm is the following approximation, which works well for <img src='http://s.wordpress.com/latex.php?latex=0%20%3C%20x_i%20%3C%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='0 &lt; x_i &lt; 1' title='0 &lt; x_i &lt; 1' class='latex' />, <img src='http://s.wordpress.com/latex.php?latex=p%20%5Cgg%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \gg 1' title='p \gg 1' class='latex' />.</p>
<img src='http://s.wordpress.com/latex.php?latex=%20%5Cmax_%7Bi%3D1%7D%5ENx_i%5Capprox%20%28%5Cfrac%7B1%7D%7BN%7D%5Csum_%7Bi%3D1%7D%5ENx_i%5Ep%29%5E%7B1%2Fp%7D%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \max_{i=1}^Nx_i\approx (\frac{1}{N}\sum_{i=1}^Nx_i^p)^{1/p} ' title=' \max_{i=1}^Nx_i\approx (\frac{1}{N}\sum_{i=1}^Nx_i^p)^{1/p} ' class='latex' />
<p>I am not going into the mathematical details of why this a fair approximation.</p>
<p>To turn this into a max filter is straightforward:</p>
<h3>1. Calculate the power image</h3>
<p>Raise each pixel to the power <em>p</em>.</p>
<img src='http://s.wordpress.com/latex.php?latex=P%28x%2C%20y%29%20%3D%20%5BI%28x%2C%20y%29%5D%5Ep&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='P(x, y) = [I(x, y)]^p' title='P(x, y) = [I(x, y)]^p' class='latex' />
<h3>2. Calculate a summed area table</h3>
<p>The <a href="http://en.wikipedia.org/wiki/Summed_area_table">summed area table</a> (or integral) of an image is a table containing in each cell (x, y), the sum of all the pixels top and left of (x, y); for the power image <img src='http://s.wordpress.com/latex.php?latex=P%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='P ' title='P ' class='latex' /> it is given by:</p>
<img src='http://s.wordpress.com/latex.php?latex=S%28x%2Cy%29%20%3D%20%5Csum_%7Bu%3D0%7D%5E%7Bx%7D%5Csum_%7Bv%3D0%7D%5E%7By%7DP%28u%2Cv%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='S(x,y) = \sum_{u=0}^{x}\sum_{v=0}^{y}P(u,v)' title='S(x,y) = \sum_{u=0}^{x}\sum_{v=0}^{y}P(u,v)' class='latex' />
<p><strong>Update:</strong> This can be efficiently be calculated using the following recurrence:</p>
<img src='http://s.wordpress.com/latex.php?latex=S%28x%2C%20y%29%20%3D%20S%28x%2C%20y%20-%201%29%20%2B%20S%28x%20-%201%2C%20y%29%20-%20S%28x%2C%20y%29%20%2B%20P%28x%2C%20y%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='S(x, y) = S(x, y - 1) + S(x - 1, y) - S(x, y) + P(x, y)' title='S(x, y) = S(x, y - 1) + S(x - 1, y) - S(x, y) + P(x, y)' class='latex' />
<p>and <img src='http://s.wordpress.com/latex.php?latex=S%28x%2C%20y%29%20%3D%200%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='S(x, y) = 0 ' title='S(x, y) = 0 ' class='latex' /> if <img src='http://s.wordpress.com/latex.php?latex=x%20%3C%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x &lt; 0' title='x &lt; 0' class='latex' /> or <img src='http://s.wordpress.com/latex.php?latex=y%20%3C%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='y &lt; 0' title='y &lt; 0' class='latex' />.</p>
<h3>3. Calculate the window mean</h3>
<p>Use the cumulative image sum to calculate the mean in the window. Here, <img src='http://s.wordpress.com/latex.php?latex=r&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='r' title='r' class='latex' /> is the window radius, <em>A</em> stands for average:</p>
<img src='http://s.wordpress.com/latex.php?latex=A%28x%2C%20y%29%20%3D%20%5Cfrac%7B1%7D%7B%282r%20%2B%201%29%5E2%7D%5BS%28x-r-1%2C%20y-r-1%29%20%2B%20S%28x%20%2B%20r%2C%20y%20%2B%20r%29-S%28x-r-1%2C%20y%20%2B%20r%29-S%28x%20%2B%20r%2C%20y-r-1%29%5D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='A(x, y) = \frac{1}{(2r + 1)^2}[S(x-r-1, y-r-1) + S(x + r, y + r)-S(x-r-1, y + r)-S(x + r, y-r-1)]' title='A(x, y) = \frac{1}{(2r + 1)^2}[S(x-r-1, y-r-1) + S(x + r, y + r)-S(x-r-1, y + r)-S(x + r, y-r-1)]' class='latex' />
<h3>4. Calculate the approximate maximum</h3>
<img src='http://s.wordpress.com/latex.php?latex=M%28x%2C%20y%29%20%3D%20%5BA%28x%2C%20y%29%5D%5E%7B1%2Fp%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='M(x, y) = [A(x, y)]^{1/p}' title='M(x, y) = [A(x, y)]^{1/p}' class='latex' />
<p>That’s it!</p>
<p>The minimum filter is implemented by finding the maximum of the inverse image and then inverting the result. This approach uses two more passes through the image; so far I could not find a direct approximation for the minimum value. (<strong>Update:</strong> It seems using <img src='http://s.wordpress.com/latex.php?latex=p%5Cll%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p\ll 0' title='p\ll 0' class='latex' /> gives an approximation for finding the minimum of a set of values.)</p>
<h2>Notes</h2>
<ul>
<li>For very large images, you might run into floating point issues when calculating the cumulative sum image. You can reduce this effect somewhat by subtracting the (total image) mean of the power image from each pixel before calculating the image sum.</li>
<li>For the image sizes I worked on, the value <img src='http://s.wordpress.com/latex.php?latex=p%3D8&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p=8' title='p=8' class='latex' /> was suitable. The higher <img src='http://s.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' />, the more accurate results, as long as you have no underflow.</li>
<li>Raising powers is a slow operation. By choosing a suitable value of <img src='http://s.wordpress.com/latex.php?latex=p&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p' title='p' class='latex' />, you can use a suitable, faster approximation for calculating the power.</li>
<li><strong>Update:</strong> It is possible to implement this as a two-pass algorithm, first working on columns, then on rows. This requires constructing two tables, which makes the algorithm slower. However, using this approach allows bigger images to be processed before overflow in the summed are tables becomes a problem.</li>
</ul>
<p>Initially I thought that once the maximum can be found, we can also find the second maximum, and so on, so that any statistical order filter can be constructed.</p>
<p>The basic idea was that if <img src='http://s.wordpress.com/latex.php?latex=m_1&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='m_1' title='m_1' class='latex' /> is the maximum, we could find the second largest value like this:</p>
<img src='http://s.wordpress.com/latex.php?latex=m_2%20%5Capprox%20%5Cfrac%7B1%7D%7BN-1%7D%5B%28%5Csum_%7Bi%3D1%7D%5EN%20x_i%5Ep%29%20-%20m_1%5Ep%5D%29%5E%7B1%2Fp%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='m_2 \approx \frac{1}{N-1}[(\sum_{i=1}^N x_i^p) - m_1^p])^{1/p}' title='m_2 \approx \frac{1}{N-1}[(\sum_{i=1}^N x_i^p) - m_1^p])^{1/p}' class='latex' />
<p>The idea is that we remove the maximum value from the sum, so that the result must yield the second largest element. Of course, we do not use the actual maximum, but the approximation—and this is where the formula fails. When we use the approximate maximum, it is easy to show that the formula above will yield the exact same approximate maximum, and not the <em>second</em> largest element.</p>
<p>I should have know it seemed too good to be true!</p>
<p><strong>Update:</strong> while looking for links for this post, I found this article: <a href="http://www.ph.tn.tudelft.nl/People/albert/papers/ICPR17VlietV13_5_13.pdf" class="broken_link">Robust Local Max-Min Filters by Normalized Power-Weighted Filtering</a> (PDF) which initially looked like it was essentially the same thing. Although it is very similar, it is in fact different. The approximate maximum is given by the value:</p>
<img src='http://s.wordpress.com/latex.php?latex=%20%5Cmax_%7Bi%3D1%7D%5ENx_i%5Capprox%20%5Cfrac%7B%5Csum_%7Bi%3D1%7D%5ENx_i%5E%7Bp%20%2B%201%7D%7D%7B%5Csum_%7Bi%3D1%7D%5ENx_i%5Ep%7D%20&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt=' \max_{i=1}^Nx_i\approx \frac{\sum_{i=1}^Nx_i^{p + 1}}{\sum_{i=1}^Nx_i^p} ' title=' \max_{i=1}^Nx_i\approx \frac{\sum_{i=1}^Nx_i^{p + 1}}{\sum_{i=1}^Nx_i^p} ' class='latex' />
<p>for <img src='http://s.wordpress.com/latex.php?latex=p%20%5Cgg%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \gg 0' title='p \gg 0' class='latex' />.</p>
<p>Using <img src='http://s.wordpress.com/latex.php?latex=p%20%5Cll%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='p \ll 0' title='p \ll 0' class='latex' /> gives an approximation to the minimum.</p>
<p>The nice thing about this approximation is that it seems to work well for all real <img src='http://s.wordpress.com/latex.php?latex=x_i&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='x_i' title='x_i' class='latex' />, not just for <img src='http://s.wordpress.com/latex.php?latex=0%20%5Cleq%20x_i%20%5Cleq%201&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='0 \leq x_i \leq 1' title='0 \leq x_i \leq 1' class='latex' />.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/' rel='bookmark' title='Permanent Link: 2D Minimum and Maximum Filters: Algorithms and Implementation Issues'>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</a></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Permanent Link: Region Quadtrees in C++'>Region Quadtrees in C++</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Experimental Tool for Removing Unwanted Artefacts in Textures</title>
		<link>http://code-spot.co.za/2010/04/15/experimental-tool-for-removing-unwanted-artefacts-in-textures/</link>
		<comments>http://code-spot.co.za/2010/04/15/experimental-tool-for-removing-unwanted-artefacts-in-textures/#comments</comments>
		<pubDate>Thu, 15 Apr 2010 13:36:40 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Tools]]></category>
		<category><![CDATA[filtering]]></category>
		<category><![CDATA[game tools]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=849</guid>
		<description><![CDATA[Many textures used for 3D art start from photographs. Ideally, such textures should be uniformly lit so that the texture does not interfere with the lighting applied by the 3D software. Often, lighting artefacts must be removed by hand. This can be tedious and time consuming. The tool provided here aims to automate this process. [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2009/05/27/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30/' rel='bookmark' title='Permanent Link: How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Example Updated for XNA 3.0.'>How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Example Updated for XNA 3.0.</a></li>
<li><a href='http://code-spot.co.za/2009/04/08/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-updated-for-xna-30/' rel='bookmark' title='Permanent Link: How to Turn XSI Mod Tool into a  Level Editor for your XNA Games: Updated for XNA 3.0.'>How to Turn XSI Mod Tool into a  Level Editor for your XNA Games: Updated for XNA 3.0.</a></li>
<li><a href='http://code-spot.co.za/2009/10/24/guerrilla-tool-development/' rel='bookmark' title='Permanent Link: Guerrilla Tool Development'>Guerrilla Tool Development</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img style="border-right: 0px; border-top: 0px; display: inline; border-left: 0px; border-bottom: 0px" title="texture" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/texture.png" border="0" alt="texture" width="491" height="321" /></p>
<p>Many textures used for 3D art start from photographs. Ideally, such textures should be uniformly lit so that the texture does not interfere with the lighting applied by the 3D software. Often, lighting artefacts must be removed by hand. This can be tedious and time consuming.</p>
<p>The tool provided here aims to automate this process. It is still in an experimental phase, so it is very crude. Below you can see some of the before and after pictures.</p>
<p><span id="more-849"></span></p>
<p>I will say more about how these work in a later post.</p>
<p>If you want to give it a try, go <a href="http://code-spot.co.za/image-restoration-tool/" class="broken_link">here</a> to download (caveats: command-line only; Windows only; requires ImageMagick.)</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="hair" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/hair.jpg" border="0" alt="hair" width="240" height="240" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="hair_std_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/hair_std_.png" border="0" alt="hair_std_" width="240" height="240" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="pebbles" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/pebbles.jpg" border="0" alt="pebbles" width="240" height="209" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="pebbles_minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/pebbles_minmax.png" border="0" alt="pebbles_minmax" width="240" height="209" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="paper" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paper.jpg" border="0" alt="paper" width="240" height="320" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="paper_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paper_mean_.png" border="0" alt="paper_mean_" width="240" height="320" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="metal" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal.jpg" border="0" alt="metal" width="240" height="117" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="metal_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal_mean_.png" border="0" alt="metal_mean_" width="240" height="117" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="metal2" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal2.jpg" border="0" alt="metal2" width="240" height="109" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="metal2_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal2_mean_.png" border="0" alt="metal2_mean_" width="240" height="109" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="machinery" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/machinery.jpg" border="0" alt="machinery" width="240" height="240" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="machinery_minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/machinery_minmax.png" border="0" alt="machinery_minmax" width="240" height="240" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="paint" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paint.jpg" border="0" alt="paint" width="240" height="180" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="paint_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paint_mean_.png" border="0" alt="paint_mean_" width="240" height="180" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="wood" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/wood.jpg" border="0" alt="wood" width="240" height="320" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="wood_std_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/wood_std_.png" border="0" alt="wood_std_" width="240" height="320" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="color" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color.jpg" border="0" alt="color" width="240" height="213" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="color_mean_2" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color_mean_2.png" border="0" alt="color_mean_2" width="240" height="213" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="color" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color.jpg" border="0" alt="color" width="240" height="213" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="color_mean_value_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color_mean_value_.png" border="0" alt="color_mean_value_" width="240" height="213" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="scene" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/scene.jpg" border="0" alt="scene" width="240" height="240" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="scene_mean" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/scene_mean.png" border="0" alt="scene_mean" width="240" height="240" /></td>
</tr>
<tr>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="grass" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/grass.jpg" border="0" alt="grass" width="240" height="160" /></td>
<td width="250" valign="top"><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="grass_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/grass_mean_.png" border="0" alt="grass_mean_" width="240" height="160" /></td>
</tr>
</tbody>
</table>
<p>The tool can also improve artefacts in tileable textures:</p>
<p><strong>BEFORE </strong>(distracting horizontal striping)</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="texture1" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/texture1.png" border="0" alt="texture1" width="500" height="375" /></p>
<p><strong>AFTER</strong> (reduced striping)</p>
<p><img style="border-top-width: 0px; display: inline; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" title="texture2" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/texture2.png" border="0" alt="texture2" width="500" height="375" /></p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2009/05/27/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-example-updated-for-xna-30/' rel='bookmark' title='Permanent Link: How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Example Updated for XNA 3.0.'>How to Turn XSI Mod Tool into a Level Editor for your XNA Games: Example Updated for XNA 3.0.</a></li>
<li><a href='http://code-spot.co.za/2009/04/08/how-to-turn-xsi-mod-tool-into-a-level-editor-for-your-xna-games-updated-for-xna-30/' rel='bookmark' title='Permanent Link: How to Turn XSI Mod Tool into a  Level Editor for your XNA Games: Updated for XNA 3.0.'>How to Turn XSI Mod Tool into a  Level Editor for your XNA Games: Updated for XNA 3.0.</a></li>
<li><a href='http://code-spot.co.za/2009/10/24/guerrilla-tool-development/' rel='bookmark' title='Permanent Link: Guerrilla Tool Development'>Guerrilla Tool Development</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/04/15/experimental-tool-for-removing-unwanted-artefacts-in-textures/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Poisson Disk Sampling Example Code</title>
		<link>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/</link>
		<comments>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/#comments</comments>
		<pubDate>Wed, 07 Apr 2010 08:57:27 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[Tutorial]]></category>
		<category><![CDATA[poisson disk]]></category>
		<category><![CDATA[procedural texture]]></category>
		<category><![CDATA[sampling]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=806</guid>
		<description><![CDATA[I decided to put the Poisson disk sampling code here for download since the site that hosted it is down. The code accompanies the tutorial on Dev.Mag: Poisson Disk Sampling. Download poisson_disk_java.zip (184 KB) poisson_disk_python.zip (912 KB) poisson_disk_ruby.zip (59 KB) Related posts:Python Image Code A simple texture algorithm – faster code and more results A [...]


Related posts:<ol><li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Permanent Link: Python Image Code'>Python Image Code</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
<li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-817" title="poisson" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/poisson3.png" alt="poisson" width="142" height="142" />I decided to put the Poisson disk sampling code here for download since the site that hosted it is down. The code accompanies the tutorial on Dev.Mag: <a href="http://www.devmag.org.za/articles/55-POISSON-DISK-SAMPLING/">Poisson Disk Sampling</a>.</p>
<h2>Download</h2>
<table border="0">
<tbody>
<tr>
<td><a href="http://www.code-spot.co.za/downloads/poisson/poisson_disk_java.zip">poisson_disk_java.zip</a> (184 KB)<br />
<a href="http://www.code-spot.co.za/downloads/poisson/poisson_disk_python.zip"> poisson_disk_python.zip</a> (912 KB)<br />
<a href="http://www.code-spot.co.za/downloads/poisson/poisson_disk_ruby.zip"> poisson_disk_ruby.zip</a> (59 KB)</td>
</tr>
</tbody>
</table>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Permanent Link: Python Image Code'>Python Image Code</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
<li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Getting More out of Seamless Tiles</title>
		<link>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/</link>
		<comments>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/#comments</comments>
		<pubDate>Thu, 28 May 2009 08:46:07 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[blending]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[grids]]></category>
		<category><![CDATA[tiles]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=620</guid>
		<description><![CDATA[I wrote an article for Dev.Mag covering some techniques for working with seamless tile sets such as making blend tiles, getting more variety with procedural colour  manipulation, tile placement strategies, and so on.  Check it out! The Python Image Code has also been updated with some of the algorithms explained in the article. Related posts:Quadtrees Quadtrees Cellular Automata [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img class="alignleft size-full wp-image-622" title="tiles_header_small" src="http://code-spot.co.za/blog/wp-content/uploads/2009/05/tiles_header_small.png" alt="tiles_header_small" width="142" height="142" />I wrote an article for Dev.Mag covering <a href="http://www.devmag.org.za/articles/70-GETTING-MORE-OUT-OF-SEAMLESS-TILES/">some techniques for working with seamless tile sets</a> such as making blend tiles, getting more variety with procedural colour  manipulation, tile placement strategies, and so on. </p>
<p>Check it out!</p>
<p>The <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a> has also been updated with some of the algorithms explained in the article.</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Permanent Link: Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2009/05/28/getting-more-out-of-seamless-tiles/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A simple texture algorithm – faster code and more results</title>
		<link>http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/</link>
		<comments>http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/#comments</comments>
		<pubDate>Mon, 15 Dec 2008 11:22:29 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[C++]]></category>
		<category><![CDATA[Downloads]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[blend animation]]></category>
		<category><![CDATA[blending]]></category>
		<category><![CDATA[optimisation]]></category>
		<category><![CDATA[Perlin noise]]></category>
		<category><![CDATA[procedural texture]]></category>
		<category><![CDATA[prototyping]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=396</guid>
		<description><![CDATA[Faster Code A while back I wrote about a simple texture algorithm that I have been exploring. The Python implementation was very slow – so much, that I decided to implement it in C++ to see what performance gain I would get. Surprisingly, the C++ version is about 100 faster, if not more. I expected [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a></li>
<li><a href='http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm'>A Simple Procedural Texture Algorithm</a></li>
<li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Permanent Link: Python Image Code'>Python Image Code</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/header.png" alt="header" width="500" height="348" /></p>
<h2>Faster Code</h2>
<p>A while back I wrote about a <a href="http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/">simple texture algorithm</a> that I have been exploring. The <a href="http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/">Python implementation</a> was <a href="http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/">very slow</a> – so much, that I decided to implement it in C++ to see what performance gain I would get. Surprisingly, the C++ version is about 100 faster, if not more. I expected a decent increase, but what once took several hours can now be done in a minute!</p>
<p><span id="more-396"></span></p>
<p>Not all of the performance gain is because of using C++ instead of Python. The Python version uses a data structure (an <a href="http://www.code-spot.co.za/downloads/python_image_code/doc/html/namespaceenhanced__grid.html">“enhanced” grid</a>) that provides a lot of fancy syntax for operating on a grid. For instance:</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="97" valign="top">grid[0, ...]</td>
<td width="400" valign="top">First column (1D)</td>
</tr>
<tr>
<td width="97" valign="top">grid[..., 1]</td>
<td width="400" valign="top">Second row (1D)</td>
</tr>
<tr>
<td width="97" valign="top">grid[0, ::2]</td>
<td width="400" valign="top">Every second item of the first column (1D)</td>
</tr>
<tr>
<td width="97" valign="top">grid[1:3,::2]</td>
<td width="400" valign="top">Every second item of the second and third column (2D)</td>
</tr>
<tr>
<td width="97" valign="top">grid[3, 4]</td>
<td width="400" valign="top">The item at the fourth column and fifth row (0D)</td>
</tr>
</tbody>
</table>
<p>The “enhanced” grid also provides several iterators that allow easy processing, for example:</p>
<ul>
<li>a cell iterator, that iterates over all values in the grid;</li>
<li>an index iterator, that iterates over all possible tuples that can be used to index the grid; and</li>
<li>a window iterator, that iterates over all cells in a rectangular portion of the grid.</li>
</ul>
<p>The speed problem is caused by the implementation that supports the above features – an implementation that I thought was rather elegant. I knew there was a performance penalty, but after seeing to what extent I realise that I must have a hard look at how these features are implemented.</p>
<p>I am a big fan of late optimisation, especially for experimental code. But this incident has made me re-evaluate my position. After I had the fast C++ version running, I could do hordes of experiments very quickly – which meant I got a much better intuition of how parameters influence the resulting texture.</p>
<p>It also made me realise how important it is to check the performance of supporting data structures, even if they are merely convenience structures in non-production code (as is the “enhanced” grid).</p>
<h2>More results</h2>
<p>One of the things that struck me about the textures that this algorithm typically produces is the shapes of blotches of similar colour. I have been trying to enhance (and take advantage) these shapes by applying various filters on the texture; below are the results.</p>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/original.png" alt="original" width="160" height="160" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/water.png" alt="water" width="160" height="160" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/brown.png" alt="brown" width="160" height="160" /></td>
</tr>
<tr>
<td width="166" valign="top">Original (generated from a random 5&#215;5 matrix)</td>
<td width="166" valign="top">Dilation</td>
<td width="166" valign="top">Posterisation</td>
</tr>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/sobel.png" alt="sobel" width="160" height="160" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/sobel-median.png" alt="sobel_median" width="160" height="160" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/edge.png" alt="edge" width="160" height="160" /></td>
</tr>
<tr>
<td width="166" valign="top">Sobel edge detection</td>
<td width="166" valign="top">Median filter and Sobel edge detection</td>
<td width="166" valign="top">Median filter, differential edge detection</td>
</tr>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/emboss.png" alt="emboss" width="160" height="160" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/alien.png" alt="alien" width="160" height="160" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/green.png" alt="green" width="160" height="160" /></td>
</tr>
<tr>
<td width="166" valign="top">Emboss</td>
<td width="166" valign="top">Alien (Gimp filter)</td>
<td width="166" valign="top">Median filter.</td>
</tr>
</tbody>
</table>
<p>The texture is also suitable for organic blend animations (compare with organic blending using <a href="http://www.luma.co.za/labs/2008/01/20/perlin-noise/" class="broken_link">Perlin noise</a>).</p>
<table border="0" cellspacing="0" cellpadding="0" width="500">
<tbody>
<tr>
<td width="83" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t1.png" alt="t1" width="80" height="80" /></td>
<td width="83" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t2.png" alt="t2" width="80" height="80" /></td>
<td width="83" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t3.png" alt="t3" width="80" height="80" /></td>
<td width="83" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t4.png" alt="t4" width="80" height="80" /></td>
<td width="83" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t5.png" alt="t5" width="80" height="80" /></td>
<td width="83" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t6.png" alt="t6" width="80" height="80" /></td>
</tr>
</tbody>
</table>
<p><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/12/t1.gif" alt="t1" width="160" height="160" /></p>
<h2>Download</h2>
<h3>C++ Implementation</h3>
<p><a href="http://www.code-spot.co.za/downloads/cpp_examples/cpp_texture.zip">cpp_texture.zip</a> (1.78 MB) (Visual Studio Solution)</p>
<p>The example uses <a href="http://pngwriter.sourceforge.net/">PNG Writer</a> , <a href="http://www.libpng.org/">libpng</a> and <a href="http://www.zlib.net/">zlib</a> (library files included with the download).</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a></li>
<li><a href='http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm'>A Simple Procedural Texture Algorithm</a></li>
<li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Permanent Link: Python Image Code'>Python Image Code</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Quadtrees</title>
		<link>http://code-spot.co.za/2008/11/15/quadtrees-2/</link>
		<comments>http://code-spot.co.za/2008/11/15/quadtrees-2/#comments</comments>
		<pubDate>Sat, 15 Nov 2008 07:28:45 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[2D]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[compression]]></category>
		<category><![CDATA[computer graphics]]></category>
		<category><![CDATA[Dev.Mag]]></category>
		<category><![CDATA[image partitioning]]></category>
		<category><![CDATA[quadtree]]></category>
		<category><![CDATA[quadtrees]]></category>
		<category><![CDATA[random]]></category>
		<category><![CDATA[spatial partitioning]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=171</guid>
		<description><![CDATA[The code below implements some quadtree extensions, as discussed in another Dev.Mag tutorial about quadtrees (see Issue 27). The tutorial covers the following topics: what to consider in choosing whether to use a quadtree or not; tests to help you choose an appropriate threshold; how to handle discrete data; and some modifications to the basic [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Permanent Link: Region Quadtrees in C++'>Region Quadtrees in C++</a></li>
<li><a href='http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm'>A Simple Procedural Texture Algorithm</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p class="MsoNormal"><span lang="EN-GB">The code below implements some quadtree extensions, as discussed in another Dev.Mag tutorial about quadtrees (see <a href="http://devmag.org.za/uploads/DevMag_Issue27.zip" class="broken_link">Issue 27</a>). The tutorial covers the following topics:</span></p>
<ul>
<li>what to consider in choosing whether to use a quadtree or not;</li>
<li>tests to help you choose an appropriate threshold;</li>
<li>how to handle discrete data; and</li>
<li>some modifications to the basic algorithm.</li>
</ul>
<h2><span lang="EN-GB">Handling Discrete Data</span></h2>
<p>When it comes to discrete data, the &#8220;average&#8221; of a number of pixels doesn&#8217;t make sense. However, we can give it meaning and still use it to get good approximations of the original data, as illustrated in the images below.</p>
<table border="0" cellspacing="0" cellpadding="2" width="451">
<tbody>
<tr>
<td width="135" valign="top"><img class="alignnone size-full wp-image-175" title="discrete_grid" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/discrete_grid.png" alt="" width="128" height="128" /></td>
<td width="312" valign="top">The original grid of discrete data. The grid contains integers from 0 to 4. Every integer is mapped to a colour in this image. (If this grid represented a tile map, every integer would be mapped to a different tile).</td>
</tr>
<tr>
<td width="135" valign="top"><img class="alignnone size-full wp-image-176" title="discrete_quadtree_normal_rounded" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/discrete_quadtree_normal_rounded.png" alt="" width="128" height="128" /></td>
<td width="312" valign="top">Here we allowed floating point numbers in the quadtree. Results of queries into the quadtree are rounded before mapping them to colours.</td>
</tr>
<tr>
<td width="135" valign="top"><img class="alignnone size-full wp-image-177" title="discrete_quadtree_normal_randomised" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/discrete_quadtree_normal_randomised.png" alt="" width="128" height="128" /></td>
<td width="312" valign="top">Here we used the floating point part of queries to bias a randomly selected integer. For example, a result of 1.25 will result in a 75% chance of yielding 2.</td>
</tr>
<tr>
<td width="135" valign="top"><img class="alignnone size-medium wp-image-178" title="discrete_quadtree_interpolated_rounded" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/discrete_quadtree_interpolated_rounded.png" alt="" width="128" height="128" /></td>
<td width="312" valign="top">Here we use a quadtree with interpolation. The result is rounded before it is mapped.</td>
</tr>
<tr>
<td width="135" valign="top"><img class="alignnone size-full wp-image-179" title="discrete_quadtree_interpolated_randomised" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/discrete_quadtree_interpolated_randomised.png" alt="" width="128" height="128" /></td>
<td width="312" valign="top">Here we use a quadtree with interpolation, and use the floating point part of the number to bias a randomly selected tile, as above.</td>
</tr>
</tbody>
</table>
<h2>Download</h2>
<h3>Python Implementation</h3>
<p>Download from: <a href="http://code-spot.co.za/python-image-code/">http://code-spot.co.za/python-image-code/</a> (See quadtree.py, quadtree_image.py, and quadtree_demo.py).</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Permanent Link: Quadtrees'>Quadtrees</a></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Permanent Link: Region Quadtrees in C++'>Region Quadtrees in C++</a></li>
<li><a href='http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm'>A Simple Procedural Texture Algorithm</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2008/11/15/quadtrees-2/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>A Simple Procedural Texture Algorithm &#8211; More Results and Code</title>
		<link>http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/</link>
		<comments>http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/#comments</comments>
		<pubDate>Fri, 14 Nov 2008 10:25:46 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Image Processing]]></category>
		<category><![CDATA[procedural texture]]></category>
		<category><![CDATA[Python]]></category>
		<category><![CDATA[random]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=268</guid>
		<description><![CDATA[In a previous post I explained a simple algorithm for generating textures. Below are some more examples of the kinds of textures that the algorithm can generate, as well as how the different parameters influence the result. You can also download the code.   The Effect of the Blend Factor t = 0 t = [...]


Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm'>A Simple Procedural Texture Algorithm</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
<li><a href='http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/' rel='bookmark' title='Permanent Link: Poisson Disk Sampling Example Code'>Poisson Disk Sampling Example Code</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<p><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/spots.png" alt="spots" width="500" height="350" /></p>
<p>In a <a href="http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/">previous post</a> I explained a simple algorithm for generating textures. Below are some more examples of the kinds of textures that the algorithm can generate, as well as how the different parameters influence the result. You can also download the <a href="http://code-spot.co.za/python-image-code/">code</a>.</p>
<p><span id="more-268"></span></p>
<table border="0" cellspacing="0" cellpadding="2" width="400">
<tbody>
<tr>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-18-49-wood.png" alt="random_corr_18_49_wood" width="140" height="140" /></td>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-96-49-fur.png" alt="random_corr_96_49_fur" width="140" height="140" /></td>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-186-49-tree.png" alt="random_corr_186_49_tree" width="140" height="140" /></td>
</tr>
<tr>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-196-49-fur.png" border="0" alt="random_corr_196_49_fur" width="140" height="140" /></td>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-260-49-wood.png" alt="random_corr_260_49_wood" width="140" height="140" /></td>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-305-49-draw.png" alt="random_corr_305_49_draw" width="140" height="140" /></td>
</tr>
<tr>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-01-49-06.png" alt="random_corr_pn_01_49_06" width="140" height="140" /></td>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/pollock.png" alt="pollock" width="140" height="140" /></td>
<td width="133" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/leaves.png" alt="leaves" width="140" height="140" /></td>
</tr>
</tbody>
</table>
<p> </p>
<h2>The Effect of the Blend Factor</h2>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="168" valign="top"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-13-00-49.png" border="0" alt="random_corr_pn_13_00_49" width="128" height="128" /></td>
<td width="167" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-01-49.png" alt="random_corr_pn_46_01_49" width="128" height="128" /></td>
<td width="163" valign="top"><img style="border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px" src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-02-49-thumb.png" border="0" alt="random_corr_pn_46_02_49" width="128" height="128" /></td>
</tr>
<tr>
<td width="168" valign="top">t = 0</td>
<td width="167" valign="top">t = 0.1</td>
<td width="163" valign="top">t = 0.2</td>
</tr>
<tr>
<td width="168" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-03-49.png" alt="random_corr_pn_46_03_49" width="128" height="128" /></td>
<td width="167" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-04-49.png" alt="random_corr_pn_46_04_49" width="128" height="128" /></td>
<td width="163" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-05-49.png" alt="random_corr_pn_46_05_49" width="128" height="128" /></td>
</tr>
<tr>
<td width="168" valign="top">t = 0.3</td>
<td width="167" valign="top">t = 0.4</td>
<td width="163" valign="top">t = 0.5</td>
</tr>
<tr>
<td width="168" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-06-49.png" alt="random_corr_pn_46_06_49" width="128" height="128" /></td>
<td width="167" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-07-49.png" alt="random_corr_pn_46_07_49" width="128" height="128" /></td>
<td width="163" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-08-49.png" alt="random_corr_pn_46_08_49" width="128" height="128" /></td>
</tr>
<tr>
<td width="168" valign="top">t = 0.6</td>
<td width="167" valign="top">t = 0.7</td>
<td width="163" valign="top">t = 0.8</td>
</tr>
<tr>
<td width="168" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-09-49.png" alt="random_corr_pn_46_09_49" width="128" height="128" /></td>
<td width="167" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-46-10-49.png" alt="random_corr_pn_46_10_49" width="128" height="128" /></td>
<td width="163" valign="top"> </td>
</tr>
<tr>
<td width="168" valign="top">t = 0.9</td>
<td width="167" valign="top">t = 1</td>
<td width="164" valign="top"> </td>
</tr>
</tbody>
</table>
<p> </p>
<h2>Effect of the Matrix</h2>
<h3>Angle</h3>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-01-05-49.png" alt="random_corr_pn_01_05_49" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-129-09-49.png" alt="random_corr_pn_129_09_49" width="128" height="128" /></td>
<td width="166" valign="top"> <img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-02-05-49.png" alt="random_corr_pn_02_05_49" width="128" height="128" /></td>
</tr>
<tr>
<td width="166" valign="top">1 0 0<br />
0 0 0<br />
0 0 0</td>
<td width="166" valign="top">1 0 0<br />
0 0 0<br />
0 1 0</td>
<td width="166" valign="top">0 1 0<br />
0 0 0<br />
0 0 0</td>
</tr>
</tbody>
</table>
<p> </p>
<h3>Spread</h3>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-84-09-49.png" alt="random_corr_pn_84_09_49" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-86-09-49.png" alt="random_corr_pn_86_09_49" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-pn-118-09-49.png" alt="random_corr_pn_118_09_49" width="128" height="128" /></td>
</tr>
<tr>
<td width="166" valign="top">001<br />
010<br />
100</td>
<td width="166" valign="top">011<br />
010<br />
100</td>
<td width="166" valign="top">011<br />
011<br />
100</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>Effect of Iteration Count</h2>
<table border="0" cellspacing="0" cellpadding="2" width="500">
<tbody>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-j-28-09-00.png" alt="random_corr_j_28_09_00" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-j-28-09-09.png" alt="random_corr_j_28_09_09" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-j-28-09-19.png" alt="random_corr_j_28_09_19" width="128" height="128" /></td>
</tr>
<tr>
<td width="166" valign="top">0</td>
<td width="166" valign="top">10</td>
<td width="166" valign="top">20</td>
</tr>
<tr>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-j-28-09-29.png" alt="random_corr_j_28_09_29" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-j-28-09-39.png" alt="random_corr_j_28_09_39" width="128" height="128" /></td>
<td width="166" valign="top"><img src="http://code-spot.co.za/blog/wp-content/uploads/2008/11/random-corr-j-28-09-49.png" alt="random_corr_j_28_09_49" width="128" height="128" /></td>
</tr>
<tr>
<td width="166" valign="top">30</td>
<td width="166" valign="top">40</td>
<td width="166" valign="top">50</td>
</tr>
</tbody>
</table>
<p> </p>
<h2>Download</h2>
<p>The code is included with <a href="http://code-spot.co.za/python-image-code/">Python Image Code</a> (see random_image.py and random_image_demo.py).</p>


<p>Related posts:<ol><li><a href='http://code-spot.co.za/2008/11/07/a-simple-procedural-texture-algorithm/' rel='bookmark' title='Permanent Link: A Simple Procedural Texture Algorithm'>A Simple Procedural Texture Algorithm</a></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='Permanent Link: A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a></li>
<li><a href='http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/' rel='bookmark' title='Permanent Link: Poisson Disk Sampling Example Code'>Poisson Disk Sampling Example Code</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

