<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>code-spot</title>
	
	<link>http://code-spot.co.za</link>
	<description>a programming blog</description>
	<lastBuildDate>Mon, 03 Jun 2013 09:15:46 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.5.1</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/code-spot" /><feedburner:info uri="code-spot" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>Pentagons</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/dOd3qVQXk1A/</link>
		<comments>http://code-spot.co.za/2013/02/20/pentagons/#comments</comments>
		<pubDate>Wed, 20 Feb 2013 00:19:35 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[AI]]></category>
		<category><![CDATA[Brocard Pentagons]]></category>
		<category><![CDATA[Cyclic Pentagons]]></category>
		<category><![CDATA[Equiangular Pentagons]]></category>
		<category><![CDATA[Equilateral Pentagons]]></category>
		<category><![CDATA[Geometry]]></category>
		<category><![CDATA[Mediocentric Pentagons]]></category>
		<category><![CDATA[Miquel's Pentagon Theorem]]></category>
		<category><![CDATA[Orthocentric Pentagons]]></category>
		<category><![CDATA[Paradiagonal Pentagons]]></category>
		<category><![CDATA[Pentagons]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[Tangent Pentagons]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1120</guid>
		<description><![CDATA[A while back I developed a mild obsession with pentagons (mathematical ones, not symbolistic!) It started when I discovered some beautiful (simple and to me, unknown) theorems of quadrangles, such as  Varignon&#8217;s theorem. I already came across Miquel&#8217;s pentagon theorem, and&#8230; <div class='yarpp-related-rss yarpp-related-none'>

No related posts.
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1121" title="pentagons" alt="" src="http://code-spot.co.za/blog/wp-content/uploads/2013/02/pentagons.png" width="488" height="277" /></p>
<p>A while back I developed a mild obsession with pentagons (mathematical ones, not symbolistic!) It started when I discovered some beautiful (simple and to me, unknown) theorems of quadrangles, such as  <a href="http://en.wikipedia.org/wiki/Varignon's_theorem">Varignon&#8217;s theorem</a>. I already came across <a href="http://demonstrations.wolfram.com/MiquelsPentagramTheorem/">Miquel&#8217;s pentagon theorem</a>, and wondered what other gems I could find.</p>
<p>Here is what I found: <a href="http://code-spot.co.za/downloads/pentagons.pdf">Pentagons (2.4 MB PDF)</a>.</p>
<p>My search was on the surface a bit disappointing: pentagons as such are not widely studied. I guess it is because some more general theorems (that apply to general polygons) contain the theory, and the specifics as applied to pentagons are not so interesting.</p>
<p>Nevertheless, I did discover a few theorems, and the journey took me into some very interesting corners of geometry; a very rewarding experience. I started to collect these into a document, which is shared below. It&#8217;s not comprehensive or complete; there are a few gaps.</p>
<p>(At some stage I may return to look at this again. In particular, there are many theorems of the type &#8220;if there is n, there is n+1&#8243;, which seems to me to hint at a very general theorem which can be used to prove a bunch of specifics.)</p>
<p>Also, when I started, I did not realise how many of the theorems will generalise to general polygons, so the collection looks a bit silly in retrospect (kind of like listing all the properties of the number 8 that equally apply to even numbers).</p>
<p>Even so, what&#8217;s done is done, and can perhaps satisfy someone else&#8217;s curiosity.</p>
<p><span id="more-1120"></span></p>
<p>Here is the list of contents:</p>
<div id="_mcePaste">
<ol>
<li>Notation
<ol>
<li>Standard labeling</li>
<li>Cycle notation (<em>I introduce a convention that to me makes it easier to keep track of symbols in my head.)</em></li>
<li>Area</li>
</ol>
</li>
<li>Five points in a plane</li>
<li>General Pentagons
<ol>
<li>Monge, Gauss, Ptolemy (<em>Theorems that have analogues for quadrangles. For example, one theorem relates the areas of six triangles spanned by certain vertices of the pentagon.</em>)</li>
<li>Cyclic Ratio Products (alla Ceva en Melenaus) (<em>Theorems involving products of cevians and other ratios.</em>)</li>
<li>Miquel (<em>Thereoms analoguous to Miquel&#8217;s theorem for triangles.</em>)</li>
<li>Conics (<em>Circumscribed and inscribed conics are uniquely determined by a pentagon.</em>)</li>
<li>Complete Pentagons (<em>Includes Miquel&#8217;s pentagram theorem.</em>)</li>
<li>The Centroid Theorem (<em>A general theorem about centroid applied to pentagons.</em>)</li>
</ol>
</li>
<li>Special Pentagons (<em>Including how to construct these pentagons.</em>)
<ol>
<li>Cyclic Pentagons (<em>Pentagons with vertices on a circle.</em>)</li>
<li>Tangent Pentagons (<em>Pentagons with all sides tangent to a circle.</em>)</li>
<li>Orthocentric Pentagons (<em>Pentagons whose altitudes intersect in a single point.</em>)</li>
<li>Mediocentric Pentagons (<em>Pentagons whose medians intersect in a single point.</em>)</li>
<li>Paradiagonal Pentagons (<em>Pentagons whose diagonals are parallel to oposite sides. Also called golden pentagons, affine regular pentagons, and equal area pentagons.</em>)</li>
<li>Equilateral Pentagons (<em>Pentagons with all sides of equal length.</em>)</li>
<li>Equiangular Pentagons (<em>Pentagons with all interior angles equal.</em>)</li>
<li>Brocard Pentagons (<em>Pentagons that have a Brocard point.</em>)</li>
<li>Classification By Subangles (<em>What the relationships between subangles imply for the pentagon.</em>)</li>
</ol>
</li>
</ol>
</div>
<h2>Download</h2>
<p><a href="http://code-spot.co.za/downloads/pentagons.pdf">Pentagons (2.4 MB PDF)</a></p>
<div class='yarpp-related-rss yarpp-related-none'>
<p>No related posts.</p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/dOd3qVQXk1A" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2013/02/20/pentagons/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2013/02/20/pentagons/</feedburner:origLink></item>
		<item>
		<title>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/EjImfOJuOkg/</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&#8230; <div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a> <small>*Fast = not toooo slow… For the image restoration tool I...</small></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a> <small>(Photo by  Darren Hester) Some algorithms take a long time...</small></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Region Quadtrees in C++'>Region Quadtrees in C++</a> <small>(Original image by GoAwayStupidAI). Below are four C++ implementations of...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1101" title="minmax" alt="" src="http://code-spot.co.za/blog/wp-content/uploads/2011/01/minmax.png" 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>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/' rel='bookmark' title='Simple, Fast* Approximate Minimum / Maximum Filters'>Simple, Fast* Approximate Minimum / Maximum Filters</a> <small>*Fast = not toooo slow… For the image restoration tool I...</small></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a> <small>(Photo by  Darren Hester) Some algorithms take a long time...</small></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Region Quadtrees in C++'>Region Quadtrees in C++</a> <small>(Original image by GoAwayStupidAI). Below are four C++ implementations of...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/EjImfOJuOkg" height="1" width="1"/>]]></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>3</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2011/01/24/2d-minimum-and-maximum-filters-algorithms-and-implementation-issues/</feedburner:origLink></item>
		<item>
		<title>Update to Functional Equations Reference (version 1.3)</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/YYsByXZmD2w/</link>
		<comments>http://code-spot.co.za/2010/09/30/update-to-functional-equations-reference-version-1-3/#comments</comments>
		<pubDate>Thu, 30 Sep 2010 11:27:07 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Mathematics]]></category>
		<category><![CDATA[Snippet]]></category>
		<category><![CDATA[difference equation]]></category>
		<category><![CDATA[discrete calculus]]></category>
		<category><![CDATA[functional equation]]></category>
		<category><![CDATA[product]]></category>
		<category><![CDATA[quotient.]]></category>
		<category><![CDATA[sum]]></category>
		<category><![CDATA[z-transform]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1073</guid>
		<description><![CDATA[This is a substantial update of this reference document. The most important addition is the chain and substitution rules for arithmetic difference calculus (ADC). Other additions include: more properties of the discrete power function, more properties of ADC operators, definitions of&#8230; <div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/difference-and-functional-equations-reference/' rel='bookmark' title='Difference and Functional Equations Reference'>Difference and Functional Equations Reference</a> <small>Original image by openDemocracy. The document below contains tables and...</small></li>
<li><a href='http://code-spot.co.za/2010/08/25/update-to-functional-equations-reference/' rel='bookmark' title='Update to Functional Equations Reference'>Update to Functional Equations Reference</a> <small>I have updated the Reference for Functional Equations. I have...</small></li>
<li><a href='http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/' rel='bookmark' title='Update: Reference for Functional Equations'>Update: Reference for Functional Equations</a> <small>In this new  version of Reference for Functional Equations I added several...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="size-full wp-image-421 alignleft" title="1052727062_0ec2c67ea4_small" src="http://code-spot.co.za/blog/wp-content/uploads/2009/02/1052727062_0ec2c67ea4_small.jpg" alt="" width="142" height="142" />This is a substantial update of this reference document. The most important addition is the chain and substitution rules for arithmetic difference calculus (ADC). Other additions include: more <span style="font-size: 13.2px;">properties of the discrete power function, more properties of ADC operators, definitions of analog functions, and ranges of convergence of (some) z-transforms. I also corrected some errors that were discovered since the last version.</span></p>
<p>Grab it <a href="http://code-spot.co.za/difference-and-functional-equations-reference/">here</a>.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/difference-and-functional-equations-reference/' rel='bookmark' title='Difference and Functional Equations Reference'>Difference and Functional Equations Reference</a> <small>Original image by openDemocracy. The document below contains tables and...</small></li>
<li><a href='http://code-spot.co.za/2010/08/25/update-to-functional-equations-reference/' rel='bookmark' title='Update to Functional Equations Reference'>Update to Functional Equations Reference</a> <small>I have updated the Reference for Functional Equations. I have...</small></li>
<li><a href='http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/' rel='bookmark' title='Update: Reference for Functional Equations'>Update: Reference for Functional Equations</a> <small>In this new  version of Reference for Functional Equations I added several...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/YYsByXZmD2w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/09/30/update-to-functional-equations-reference-version-1-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2010/09/30/update-to-functional-equations-reference-version-1-3/</feedburner:origLink></item>
		<item>
		<title>Update to Functional Equations Reference</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/QhpqNldqJnM/</link>
		<comments>http://code-spot.co.za/2010/08/25/update-to-functional-equations-reference/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 10:59:04 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Snippet]]></category>
		<category><![CDATA[difference equation]]></category>
		<category><![CDATA[discrete calculus]]></category>
		<category><![CDATA[functional equation]]></category>
		<category><![CDATA[z-transform]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1061</guid>
		<description><![CDATA[I have updated the Reference for Functional Equations. I have added several entries to the tables, updated the graphs, added some new graphs, added some explanations and additional notes on notation, corrected a few typos, and re-organised the document slightly.&#8230; <div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/' rel='bookmark' title='Update: Reference for Functional Equations'>Update: Reference for Functional Equations</a> <small>In this new  version of Reference for Functional Equations I added several...</small></li>
<li><a href='http://code-spot.co.za/difference-and-functional-equations-reference/' rel='bookmark' title='Difference and Functional Equations Reference'>Difference and Functional Equations Reference</a> <small>Original image by openDemocracy. The document below contains tables and...</small></li>
<li><a href='http://code-spot.co.za/2010/09/30/update-to-functional-equations-reference-version-1-3/' rel='bookmark' title='Update to Functional Equations Reference (version 1.3)'>Update to Functional Equations Reference (version 1.3)</a> <small>This is a substantial update of this reference document. The...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="size-full wp-image-421 alignleft" title="1052727062_0ec2c67ea4_small" src="http://code-spot.co.za/blog/wp-content/uploads/2009/02/1052727062_0ec2c67ea4_small.jpg" alt="" width="142" height="142" />I have updated the <em>Reference for Functional Equations</em>. I have added several entries to the tables, updated the graphs, added some new graphs, added some explanations and additional notes on notation, corrected a few typos, and re-organised the document slightly. Get the new version <a href="http://code-spot.co.za/difference-and-functional-equations-reference/">here</a>.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/2009/05/27/update-reference-for-functional-equations/' rel='bookmark' title='Update: Reference for Functional Equations'>Update: Reference for Functional Equations</a> <small>In this new  version of Reference for Functional Equations I added several...</small></li>
<li><a href='http://code-spot.co.za/difference-and-functional-equations-reference/' rel='bookmark' title='Difference and Functional Equations Reference'>Difference and Functional Equations Reference</a> <small>Original image by openDemocracy. The document below contains tables and...</small></li>
<li><a href='http://code-spot.co.za/2010/09/30/update-to-functional-equations-reference-version-1-3/' rel='bookmark' title='Update to Functional Equations Reference (version 1.3)'>Update to Functional Equations Reference (version 1.3)</a> <small>This is a substantial update of this reference document. The...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/QhpqNldqJnM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/08/25/update-to-functional-equations-reference/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2010/08/25/update-to-functional-equations-reference/</feedburner:origLink></item>
		<item>
		<title>A Simple Trick for Moving Objects in a Physics Simulation</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/G_SjemtV6eI/</link>
		<comments>http://code-spot.co.za/2010/07/27/a-simple-trick-for-moving-objects-in-a-physics-simulation/#comments</comments>
		<pubDate>Tue, 27 Jul 2010 19:24:24 +0000</pubDate>
		<dc:creator>herman.tulleken</dc:creator>
				<category><![CDATA[Algorithms]]></category>
		<category><![CDATA[Game Development]]></category>
		<category><![CDATA[Simulation]]></category>
		<category><![CDATA[damper]]></category>
		<category><![CDATA[force]]></category>
		<category><![CDATA[game programming]]></category>
		<category><![CDATA[physics]]></category>
		<category><![CDATA[PID controller]]></category>
		<category><![CDATA[spring]]></category>

		<guid isPermaLink="false">http://code-spot.co.za/?p=1013</guid>
		<description><![CDATA[(Original Image by Valerie Everett) It is sometime necessary to move an object in a physics simulation to a specific point. On the one hand, it can be difficult to analyse the exact force you have to apply; on the&#8230; <div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a> <small>A cellular automata system is one of the best demonstrations...</small></li>
<li><a href='http://code-spot.co.za/2008/12/07/random-steering-7-components-for-a-toolkit/' rel='bookmark' title='Random Steering &#8211; 7 Components for a Toolkit'>Random Steering &#8211; 7 Components for a Toolkit</a> <small>Random steering is often a useful for simulating interesting steering...</small></li>
<li><a href='http://code-spot.co.za/2008/10/29/force-field-editor-v10/' rel='bookmark' title='Force Field Editor v1.0'>Force Field Editor v1.0</a> <small>Vector fields are used in certain AI and simulation techniques....</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="alignnone size-full wp-image-1035" title="springs" alt="" src="http://code-spot.co.za/blog/wp-content/uploads/2010/07/springs2.png" width="488" height="257" /></p>
<p>(<a href="http://www.flickr.com/photos/valeriebb/248282508/sizes/o/">Original Image</a> by <a href="http://www.flickr.com/photos/valeriebb/">Valerie Everett</a>)</p>
<p>It is sometime necessary to move an object in a physics simulation to a specific point. On the one hand, it can be difficult to analyse the exact force you have to apply; on the other hand it might not look so good if you animate the object&#8217;s position directly.</p>
<p>A compromise that works well in many situations is to use a spring-damper system to move the object.</p>
<p>The trick is simple: we apply two forces—the one is proportional to the displacement; the other is proportional to the velocity. Tweaked correctly, they combine to give realistic movement to the desired point.</p>
<p><span id="more-1013"></span></p>
<p>The <a href="http://en.wikipedia.org/wiki/Hookes_law"><em>spring force</em></a> is proportional to the difference between the current position and the position where we want the object:</p>
<img src='http://s.wordpress.com/latex.php?latex=F_s%20%3D%20-k%28x%20-%20x_0%29&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='F_s = -k(x - x_0)' title='F_s = -k(x - x_0)' class='latex' />
<p>Here, <img src='http://s.wordpress.com/latex.php?latex=k&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='k' title='k' class='latex' /> is a positive value called the <em>spring constant</em>.</p>
<p>As you can see, the force gets smaller as our object approaches the desired position, and becomes zero when it reaches that position. Unfortunately, in the absence of friction or drag, the <em>velocity</em> is not zero at this point, so the object overshoots the desired position, and moves past it. The force becomes bigger, but in the opposite direction. The object keeps on moving, slowing down, and finally starts moving in the opposite direction towards the desired position. This goes on indefinitely.</p>
<p>When there is friction or drag, we might be lucky enough for the system to slow down the object sufficiently so that its velocity becomes zero when the object reaches the desired position. This can be tricky to accomplish, though, and might impact the simulation environment in undesirable ways.</p>
<p>It is better to add a counteracting force explicitly. We add a <em>damper force</em> that is propostional to the velocity of the object, again opposite in direction. Here <img src='http://s.wordpress.com/latex.php?latex=c&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c' title='c' class='latex' /> is the <em>viscous damping coefficient</em>, also a positive number.</p>
<img src='http://s.wordpress.com/latex.php?latex=F_d%20%3D%20-cv&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='F_d = -cv' title='F_d = -cv' class='latex' />
<p>We then apply the sum of the forces to our object:</p>
<img src='http://s.wordpress.com/latex.php?latex=F_t%20%3D%20F_s%20%2B%20F_d&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='F_t = F_s + F_d' title='F_t = F_s + F_d' class='latex' />
<p>The trick is to choose <img src='http://s.wordpress.com/latex.php?latex=c&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c' title='c' class='latex' /> to get the behaviour we want.</p>
<p>Fortunately, this is easy. The following table summarizes how the damping constant affects behaviour. Here, <img src='http://s.wordpress.com/latex.php?latex=m&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='m' title='m' class='latex' /> is the mass of the object.</p>
<table>
<tbody>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=c%20%3D%200&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c = 0' title='c = 0' class='latex' /></td>
<td>The object oscillates.</td>
</tr>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=0%20%3C%20c%20%3C%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='0 &lt; c &lt; 2\sqrt{mk}' title='0 &lt; c &lt; 2\sqrt{mk}' class='latex' /></td>
<td>The object oscillates, but the oscillations die down.</td>
</tr>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=c%20%3D%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c = 2\sqrt{mk}' title='c = 2\sqrt{mk}' class='latex' /></td>
<td>The object moves to the desired position without oscillating in minimum time.</td>
</tr>
<tr>
<td><img src='http://s.wordpress.com/latex.php?latex=c%20%3E%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c &gt; 2\sqrt{mk}' title='c &gt; 2\sqrt{mk}' class='latex' /></td>
<td>The object moves to the desired position without oscillating, and takes longer as c increases.</td>
</tr>
</tbody>
</table>
<p>If you want to see an explanation of how this works, see the Wikipedia article on <a href="http://en.wikipedia.org/wiki/Damping">damping</a>.</p>
<p>By choosing <img src='http://s.wordpress.com/latex.php?latex=c%20%3D%202%5Csqrt%7Bmk%7D&#038;bg=ffffff&#038;fg=000000&#038;s=0' alt='c = 2\sqrt{mk}' title='c = 2\sqrt{mk}' class='latex' />, we are left with only one parameter to tweak (the spring constant), with which we can adjust the time it will take for the object to reach the desired spot.</p>
<p>A simple implementation of this idea is given by the following function. The function should be called for every simulation frame, until we are satisfied that the object reached its spot:</p>
<pre>private void MoveTo(Rigidbody rigidbody, Vector3 newPosition,
      float springConstant)
{
  Vector3 desiredDisplacement = rigidbody.position - newPosition;
  Vector3 springForce = -springConstant * desiredDisplacement;

  float viscousDampingCoefficient
    = 2 * sqrt(rigidbody.mass * springConstant);

  Vector3 dampingForce
    = -viscousDampingCoefficient * rigidbody.velocity;

  Vector3 totalForce = springForce + dampingForce;
  rigidbody.AddForce(totalForce);
}</pre>
<p>This will work even when there is drag or friction, except that the object will move slower (in this case we can decrease the artificial damping, although it is a bit risky). When there is an external force applied to the object, the object will come to rest at some point away from the desired position. By increasing the spring constant, the distance between this point and the desired point can be made smaller. Thus, we can also use this scheme to maintain objects at a certain height, for example, which can give a rather realistic simulation of a hovercraft or even a drifting object.</p>
<p><strong>Update: </strong>This is an example of a <a href="http://en.wikipedia.org/wiki/PID_controller">PID controller</a> (proportional–integral–derivative controller), for which there is a C++ implementation in my <a href="http://code.google.com/p/specialnumbers/">Special Numbers Library</a>.</p>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/2009/04/09/cellular-automata-for-simulation-in-games/' rel='bookmark' title='Cellular Automata for Simulation in Games'>Cellular Automata for Simulation in Games</a> <small>A cellular automata system is one of the best demonstrations...</small></li>
<li><a href='http://code-spot.co.za/2008/12/07/random-steering-7-components-for-a-toolkit/' rel='bookmark' title='Random Steering &#8211; 7 Components for a Toolkit'>Random Steering &#8211; 7 Components for a Toolkit</a> <small>Random steering is often a useful for simulating interesting steering...</small></li>
<li><a href='http://code-spot.co.za/2008/10/29/force-field-editor-v10/' rel='bookmark' title='Force Field Editor v1.0'>Force Field Editor v1.0</a> <small>Vector fields are used in certain AI and simulation techniques....</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/G_SjemtV6eI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/07/27/a-simple-trick-for-moving-objects-in-a-physics-simulation/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2010/07/27/a-simple-trick-for-moving-objects-in-a-physics-simulation/</feedburner:origLink></item>
		<item>
		<title>Region Quadtrees in C++</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/bK0nqG364b0/</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&#8230; <div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Quadtrees'>Quadtrees</a> <small>The quadtree is an important 2D data structure and forms...</small></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Quadtrees'>Quadtrees</a> <small>The code below implements some quadtree extensions, as discussed in...</small></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a> <small>Faster Code A while back I wrote about a simple...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img style="display: inline; border: 0px;" title="quadtree" alt="quadtree" src="http://code-spot.co.za/blog/wp-content/uploads/2010/06/quadtree.png" width="491" height="375" border="0" /></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 width="500" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td style="text-align: left;" valign="top" width="100">(milliseconds)</td>
<td style="text-align: right;" valign="top" width="100"><strong>N</strong></td>
<td style="text-align: right;" valign="top" width="100"><strong>S</strong></td>
<td style="text-align: right;" valign="top" width="100"><strong>AST</strong></td>
<td style="text-align: right;" valign="top" width="100"><strong>AAST</strong></td>
</tr>
<tr>
<td style="text-align: right;" valign="top" width="100"></td>
<td style="text-align: right;" valign="top" width="100">3</td>
<td style="text-align: right;" valign="top" width="100">4</td>
<td style="text-align: right;" valign="top" width="100">4</td>
<td style="text-align: right;" valign="top" width="100">3</td>
</tr>
<tr>
<td valign="top" width="100"><strong>64×64</strong></td>
<td style="text-align: right;" valign="top" width="100">14</td>
<td style="text-align: right;" valign="top" width="100">14</td>
<td style="text-align: right;" valign="top" width="100">14</td>
<td style="text-align: right;" valign="top" width="100">13</td>
</tr>
<tr>
<td valign="top" width="100"><strong>128×128</strong></td>
<td style="text-align: right;" valign="top" width="100">55</td>
<td style="text-align: right;" valign="top" width="100">52</td>
<td style="text-align: right;" valign="top" width="100">55</td>
<td style="text-align: right;" valign="top" width="100">52</td>
</tr>
<tr>
<td valign="top" width="100"><strong>256×256</strong></td>
<td style="text-align: right;" valign="top" width="100">229</td>
<td style="text-align: right;" valign="top" width="100">233</td>
<td style="text-align: right;" valign="top" width="100">218</td>
<td style="text-align: right;" valign="top" width="100">214</td>
</tr>
<tr>
<td valign="top" width="100"><strong>512×512</strong></td>
<td style="text-align: right;" valign="top" width="100">950</td>
<td style="text-align: right;" valign="top" width="100">1036</td>
<td style="text-align: right;" valign="top" width="100">937</td>
<td style="text-align: right;" valign="top" width="100">922</td>
</tr>
<tr>
<td valign="top" width="100"><strong>1024×1024</strong></td>
<td style="text-align: right;" valign="top" width="100">4064</td>
<td style="text-align: right;" valign="top" width="100">4459</td>
<td style="text-align: right;" valign="top" width="100">5396</td>
<td style="text-align: right;" valign="top" width="100">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>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/2008/10/06/quadtrees/' rel='bookmark' title='Quadtrees'>Quadtrees</a> <small>The quadtree is an important 2D data structure and forms...</small></li>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Quadtrees'>Quadtrees</a> <small>The code below implements some quadtree extensions, as discussed in...</small></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a> <small>Faster Code A while back I wrote about a simple...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/bK0nqG364b0" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/</feedburner:origLink></item>
		<item>
		<title>Catching Common Image Processing Programming Errors with Generic Unit Tests</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/jep2TCGklQ0/</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&#8230; <div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Quadtrees'>Quadtrees</a> <small>The code below implements some quadtree extensions, as discussed in...</small></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Region Quadtrees in C++'>Region Quadtrees in C++</a> <small>(Original image by GoAwayStupidAI). Below are four C++ implementations of...</small></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a> <small>(Photo by  Darren Hester) Some algorithms take a long time...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="size-full wp-image-947 aligncenter" title="crash test dummy" alt="crash test dummy" src="http://code-spot.co.za/blog/wp-content/uploads/2010/05/dummy1.png" 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 valign="top" width="140"><code>flipVertical<br />
</code><code>flipHorizontal</code></td>
<td valign="top" width="340">Off-by-one errors.</td>
</tr>
<tr>
<td valign="top" width="140"><code>flipDiagonal</code></td>
<td valign="top" width="340">Swapping x and y.</td>
</tr>
<tr>
<td valign="top" width="140"><code>rotateChannels</code></td>
<td valign="top" width="340">Working on the wrong channel.</td>
</tr>
<tr>
<td valign="top" width="140"><code>invert</code></td>
<td valign="top" width="340">Calculation mistakes, certain kinds of division-by-zero. errors.</td>
</tr>
<tr>
<td valign="top" width="140"><code>scaleIntensity</code></td>
<td valign="top" width="340">Calculation mistakes.</td>
</tr>
<tr>
<td valign="top" width="140"><code>adjustGamma</code></td>
<td valign="top" width="340">Certain kinds of statistical ordering errors.</td>
</tr>
<tr>
<td valign="top" width="140"><code>crop</code></td>
<td valign="top" width="340">Certain kind of incorrect border calculations, certain power-of-two errors.</td>
</tr>
<tr>
<td valign="top" width="140"><code>translateVertival<br />
</code><code>translateHorizontal</code></td>
<td valign="top" width="340">Certain kinds of incorrect border calculations, off-by-one errors.</td>
</tr>
<tr>
<td valign="top" width="140"><code>desaturate</code></td>
<td valign="top" width="340">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 valign="top" width="158"><code>ignore_none</code></td>
<td valign="top" width="340">A constant array of 1s. Probably the one to be used with most algorithms.</td>
</tr>
<tr>
<td valign="top" width="158"><code>ignore_value</code><br />
<code>ignore_values</code></td>
<td valign="top" width="340">Ignores all the pixels in the test data that equal a given value or list of values.</td>
</tr>
<tr>
<td valign="top" width="158"><code>ignore_range</code></td>
<td valign="top" width="340">Ignores all the pixels in the test data that fall in the given range.</td>
</tr>
<tr>
<td valign="top" width="158"><code>ignore_out_of_range</code></td>
<td valign="top" width="340">Ignores all the pixels in the test data that fall outside a given range.</td>
</tr>
<tr>
<td valign="top" width="158"><code>ignore_rect</code></td>
<td valign="top" width="340">Ignores all the pixels inside a specified rectangle.</td>
</tr>
<tr>
<td valign="top" width="158"><code>ignore_border</code></td>
<td valign="top" width="340">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&amp;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>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/2008/11/15/quadtrees-2/' rel='bookmark' title='Quadtrees'>Quadtrees</a> <small>The code below implements some quadtree extensions, as discussed in...</small></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Region Quadtrees in C++'>Region Quadtrees in C++</a> <small>(Original image by GoAwayStupidAI). Below are four C++ implementations of...</small></li>
<li><a href='http://code-spot.co.za/2008/11/11/5-tips-for-prototyping-slow-algorithms/' rel='bookmark' title='5 Tips for Prototyping Slow Algorithms'>5 Tips for Prototyping Slow Algorithms</a> <small>(Photo by  Darren Hester) Some algorithms take a long time...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/jep2TCGklQ0" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://code-spot.co.za/2010/05/12/catching-common-image-processing-programming-errors-with-generic-unit-tests/</feedburner:origLink></item>
		<item>
		<title>Simple, Fast* Approximate Minimum / Maximum Filters</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/07Ofkkl85bs/</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&#8230; <div class='yarpp-related-rss'>

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='2D Minimum and Maximum Filters: Algorithms and Implementation Issues'>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</a> <small>A while back I needed to implement fast minimum and...</small></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Region Quadtrees in C++'>Region Quadtrees in C++</a> <small>(Original image by GoAwayStupidAI). Below are four C++ implementations of...</small></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a> <small>Faster Code A while back I wrote about a simple...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="aligncenter" style="display: inline; border: 0px initial initial;" title="minmax" alt="minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/minmax.png" width="491" height="321" border="0" /></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">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>
<div class='yarpp-related-rss'>
<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='2D Minimum and Maximum Filters: Algorithms and Implementation Issues'>2D Minimum and Maximum Filters: Algorithms and Implementation Issues</a> <small>A while back I needed to implement fast minimum and...</small></li>
<li><a href='http://code-spot.co.za/2010/06/15/region-quadtrees-in-c/' rel='bookmark' title='Region Quadtrees in C++'>Region Quadtrees in C++</a> <small>(Original image by GoAwayStupidAI). Below are four C++ implementations of...</small></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a> <small>Faster Code A while back I wrote about a simple...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/07Ofkkl85bs" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://code-spot.co.za/2010/04/16/simple-fast-approximate-minimum-maximum-filters/</feedburner:origLink></item>
		<item>
		<title>Experimental Tool for Removing Unwanted Artefacts in Textures</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/ve5APtFRHhE/</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&#8230; <div class='yarpp-related-rss'>

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='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> <small>The example for the tutorial How to Turn XSI Mod Tool...</small></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='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> <small>Last year I wrote a tutorial explaining how to use...</small></li>
<li><a href='http://code-spot.co.za/2009/10/24/guerrilla-tool-development/' rel='bookmark' title='Guerrilla Tool Development'>Guerrilla Tool Development</a> <small>Tools for editing game levels and AI for your own...</small></li>
</ol>
</div>
]]></description>
				<content:encoded><![CDATA[<p><img class="aligncenter" style="display: inline; border: 0px;" title="texture" alt="texture" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/texture.png" width="491" height="321" border="0" /></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 width="500" border="0" cellspacing="0" cellpadding="2">
<tbody>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="hair" alt="hair" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/hair.jpg" width="240" height="240" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="hair_std_" alt="hair_std_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/hair_std_.png" width="240" height="240" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="pebbles" alt="pebbles" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/pebbles.jpg" width="240" height="209" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="pebbles_minmax" alt="pebbles_minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/pebbles_minmax.png" width="240" height="209" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="paper" alt="paper" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paper.jpg" width="240" height="320" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="paper_mean_" alt="paper_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paper_mean_.png" width="240" height="320" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="metal" alt="metal" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal.jpg" width="240" height="117" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="metal_mean_" alt="metal_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal_mean_.png" width="240" height="117" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="metal2" alt="metal2" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal2.jpg" width="240" height="109" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="metal2_mean_" alt="metal2_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/metal2_mean_.png" width="240" height="109" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="machinery" alt="machinery" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/machinery.jpg" width="240" height="240" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="machinery_minmax" alt="machinery_minmax" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/machinery_minmax.png" width="240" height="240" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="paint" alt="paint" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paint.jpg" width="240" height="180" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="paint_mean_" alt="paint_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/paint_mean_.png" width="240" height="180" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="wood" alt="wood" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/wood.jpg" width="240" height="320" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="wood_std_" alt="wood_std_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/wood_std_.png" width="240" height="320" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="color" alt="color" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color.jpg" width="240" height="213" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="color_mean_2" alt="color_mean_2" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color_mean_2.png" width="240" height="213" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="color" alt="color" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color.jpg" width="240" height="213" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="color_mean_value_" alt="color_mean_value_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/color_mean_value_.png" width="240" height="213" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="scene" alt="scene" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/scene.jpg" width="240" height="240" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="scene_mean" alt="scene_mean" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/scene_mean.png" width="240" height="240" border="0" /></td>
</tr>
<tr>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="grass" alt="grass" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/grass.jpg" width="240" height="160" border="0" /></td>
<td valign="top" width="250"><img style="display: inline; border-width: 0px;" title="grass_mean_" alt="grass_mean_" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/grass_mean_.png" width="240" height="160" border="0" /></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="display: inline; border-width: 0px;" title="texture1" alt="texture1" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/texture1.png" width="500" height="375" border="0" /></p>
<p><strong>AFTER</strong> (reduced striping)</p>
<p><img style="display: inline; border-width: 0px;" title="texture2" alt="texture2" src="http://code-spot.co.za/blog/wp-content/uploads/2010/04/texture2.png" width="500" height="375" border="0" /></p>
<div class='yarpp-related-rss'>
<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='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> <small>The example for the tutorial How to Turn XSI Mod Tool...</small></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='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> <small>Last year I wrote a tutorial explaining how to use...</small></li>
<li><a href='http://code-spot.co.za/2009/10/24/guerrilla-tool-development/' rel='bookmark' title='Guerrilla Tool Development'>Guerrilla Tool Development</a> <small>Tools for editing game levels and AI for your own...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/ve5APtFRHhE" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://code-spot.co.za/2010/04/15/experimental-tool-for-removing-unwanted-artefacts-in-textures/</feedburner:origLink></item>
		<item>
		<title>Poisson Disk Sampling Example Code</title>
		<link>http://feedproxy.google.com/~r/code-spot/~3/6viEui62ce8/</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)<div class='yarpp-related-rss'>

Related posts:<ol>
<li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Python Image Code'>Python Image Code</a> <small>I use this code to illustrate many of the tutorials...</small></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a> <small>Faster Code A while back I wrote about a simple...</small></li>
<li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a> <small>In a previous post I explained a simple algorithm for...</small></li>
</ol>
</div>
]]></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>
<div class='yarpp-related-rss'>
<p>Related posts:<ol>
<li><a href='http://code-spot.co.za/python-image-code/' rel='bookmark' title='Python Image Code'>Python Image Code</a> <small>I use this code to illustrate many of the tutorials...</small></li>
<li><a href='http://code-spot.co.za/2008/12/15/a-simple-texture-algorithm-faster-code-and-more-results/' rel='bookmark' title='A simple texture algorithm – faster code and more results'>A simple texture algorithm – faster code and more results</a> <small>Faster Code A while back I wrote about a simple...</small></li>
<li><a href='http://code-spot.co.za/2008/11/14/a-simple-procedural-texture-algorithm-more-results-and-code/' rel='bookmark' title='A Simple Procedural Texture Algorithm &#8211; More Results and Code'>A Simple Procedural Texture Algorithm &#8211; More Results and Code</a> <small>In a previous post I explained a simple algorithm for...</small></li>
</ol></p>
</div>
<img src="http://feeds.feedburner.com/~r/code-spot/~4/6viEui62ce8" height="1" width="1"/>]]></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>
		<feedburner:origLink>http://code-spot.co.za/2010/04/07/poisson-disk-sampling-example-code/</feedburner:origLink></item>
	</channel>
</rss>
