<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>More Than Technical &#187; graphics</title>
	<atom:link href="http://www.morethantechnical.com/category/graphics/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.morethantechnical.com</link>
	<description>On software, code, the internet and more.</description>
	<lastBuildDate>Mon, 06 Feb 2012 23:48:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
<atom:link rel="hub" href="http://pubsubhubbub.appspot.com"/><atom:link rel="hub" href="http://superfeedr.com/hubbub"/>		<item>
		<title>Structure from Motion and 3D reconstruction on the easy in OpenCV 2.3+ [w/ code]</title>
		<link>http://www.morethantechnical.com/2012/02/07/structure-from-motion-and-3d-reconstruction-on-the-easy-in-opencv-2-3-w-code/</link>
		<comments>http://www.morethantechnical.com/2012/02/07/structure-from-motion-and-3d-reconstruction-on-the-easy-in-opencv-2-3-w-code/#comments</comments>
		<pubDate>Mon, 06 Feb 2012 23:48:17 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[3d]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Recommended]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[vision]]></category>
		<category><![CDATA[Website]]></category>
		<category><![CDATA[fundamental]]></category>
		<category><![CDATA[matrix]]></category>
		<category><![CDATA[motion]]></category>
		<category><![CDATA[reconstruction]]></category>
		<category><![CDATA[sfm]]></category>
		<category><![CDATA[structure]]></category>
		<category><![CDATA[triangulation]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=998</guid>
		<description><![CDATA[Hello This time I&#8217;ll discuss a basic implementation of a Structure from Motion method, following the steps Hartley and Zisserman show in &#8220;The Bible&#8221; book: &#8220;Multiple View Geometry&#8221;. I will show how simply their linear method can be implemented in OpenCV. I treat this as a kind of tutorial, or a toy example, of how [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-06-at-6.44.42-PM.png" rel="lightbox[998]"><img class="alignleft size-medium wp-image-1064" title="SfM toy example" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-06-at-6.44.42-PM-300x71.png" alt="" width="300" height="71" /></a>Hello<br />
This time I&#8217;ll discuss a basic implementation of a Structure from Motion method, following the steps Hartley and Zisserman show in &#8220;The Bible&#8221; book: &#8220;Multiple View Geometry&#8221;. I will show how simply their linear method can be implemented in OpenCV.</p>
<p>I treat this as a kind of tutorial, or a toy example, of how to perform Structure from Motion in OpenCV.</p>
<p>Let&#8217;s get down to business&#8230;<br />
<span id="more-998"></span></p>
<h2>Getting a motion map</h2>
<p>The basic thing when doing reconstruction from pairs of images, is that you know the motion: How much &#8220;a pixel has moved&#8221; from one image to the other. This gives you the ability to reconstruct it&#8217;s distance from the camera(s). So our first goal is to try and understand that from a pair of two images.</p>
<p>In calibrated horizontal stereo rigs this is called <em>Disparity</em>, and it refers to the horizontal motion of a pixel. And OpenCV actually has some very good tools to recover horizontal disparity, that can be seen in this <a href="https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/stereo_match.cpp" target="_blank">sample</a>.</p>
<p>But in our case we don&#8217;t have a calibrated rig as we are doing monocular (one camera) depth reconstruction, or in other words: <em>Structure from motion</em>.</p>
<p>You can go about getting a motion map in many different ways, but two canonical ways are: optical flow and feature matching.<br />
Also, I will stick to what OpenCV has to offer, but obviously there is a whole lot of work.</p>
<div id="attachment_1051" class="wp-caption aligncenter" style="width: 562px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.52.31-AM.png" rel="lightbox[998]"><img class="size-full wp-image-1051 " title="Input Images" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.52.31-AM.png" alt="" width="552" height="209" /></a><p class="wp-caption-text">Input pair of images, rotation and translation is unknown</p></div>
<h4>Optical Flow</h4>
<p>In optical flow you basically try to &#8220;track the pixels&#8221; from image 1 to 2, usually assuming a pixel can move only within a certain <em>window</em> in which you will search. OpenCV offers some ways to do optical flow, but I will focus on the newer and nicer one: Farenback&#8217;s method for dense optical flow.<br />
The word <em>dense</em> means we look for the motion for <em>every pixel in the image</em>. This is usually costly, but Farneback&#8217;s method is linear which is easy to solve, and they have a rocking implementation of it in OpenCV so it basically flies.<br />
Running the function on two images will provide a motion map, however my experiments show that this map is wrong in a fair bit of the times&#8230; To cope with that, I am doing an iterative operation, also leveraging the fact the this OF method can use an initial guess.<br />
An example of using Farneback method exists in the samples directory of OpenCV&#8217;s repo: <a href="https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/fback.cpp" target="_blank">here</a>.</p>
<div id="attachment_1050" class="wp-caption aligncenter" style="width: 334px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.52.04-AM.png" rel="lightbox[998]"><img class="size-full wp-image-1050" title="Screen shot 2012-02-05 at 12.52.04 AM" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.52.04-AM.png" alt="" width="324" height="266" /></a><p class="wp-caption-text">Dense O-F using Farneback</p></div>
<h4>Feature Matching</h4>
<p>The other way of getting motion is matching features between the two images.<br />
In each image we extract salient features and invariant descriptors, and then match the two sets of features.<br />
It&#8217;s very easily done in OpenCV and widely covered by <a href="https://code.ros.org/svn/opencv/trunk/opencv/samples/cpp/matcher_simple.cpp" target="_blank">examples</a> and <a href="http://opencv.itseez.com/doc/tutorials/features2d/table_of_content_features2d/table_of_content_features2d.html" target="_blank">tutorials</a>.<br />
This method however, will not provide a dense motion map. It will provide a very sparse one at best&#8230; so that depth reconstruction will also be sparse. We may talk about how to overcome that by hacking some segmentation methods, like superpixels and graph-cuts, in a different post.</p>
<div id="attachment_1049" class="wp-caption aligncenter" style="width: 653px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.51.34-AM.png" rel="lightbox[998]"><img class="size-full wp-image-1049" title="Screen shot 2012-02-05 at 12.51.34 AM" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.51.34-AM.png" alt="" width="643" height="264" /></a><p class="wp-caption-text">SURF features matching, with Fundamental matrix pruning via RANSAC</p></div>
<h4>A hybrid method</h4>
<p>Another way that I am working on to get motion is a hybrid between Feature Matching and Optical Flow.<br />
Basically the idea is to perform feature matching at first, and then O-F. When the motion is big, and features move quite a lot in the image, O-F sometimes fails (because pixel movement is usually confined to a search window).<br />
After we get features pairs, we can try to recover a global movement in the image. We use that movement as an initial guess for O-F.</p>
<div id="attachment_1052" class="wp-caption aligncenter" style="width: 333px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.51.50-AM.png" rel="lightbox[998]"><img class="size-full wp-image-1052" title="Rigid transform flow" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-12.51.50-AM.png" alt="" width="323" height="265" /></a><p class="wp-caption-text">The rigid transform flow recovered from sparse feature matching</p></div>
<h2>Estimating Motion</h2>
<p>Once we have a motion map between the two images, it should pose no problem to recover the motion of the camera. The motion is described in the 3&#215;4 matrix P, which is combined of two elements: P = [R|t], which are the Rotational element R and Translational element t.<br />
H&amp;Z give us a bunch of ways of recovering the P matrices for both cameras in Chapter 9 of their book. The central method being &#8211; using the <a href="http://en.wikipedia.org/wiki/Fundamental_matrix_(computer_vision)" target="_blank">Fundamental Matrix</a>. This special 3&#215;3 matrix encodes the epipolar constraint between the images, to put simply: for each point x in image 1 and corresponding point x&#8217; in image 2 the following equation holds: x&#8217;Fx = 0.<br />
How does that help us? Well H&amp;Z also prove that if you have F, you can infer the two P matrices. And, if you have (sufficient) point matches between images, which we have, you can find F! Hurray!<br />
This is simply visible in the linear sense. F has 9 entries (but only 8 degrees of freedom), so if we have enough point pairs, we can solve for F in a least squares sense. But&#8230; F is better estimated in a more robust way, and OpenCV takes care of all of this for us in the function <a href="http://opencv.itseez.com/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html?highlight=findfundamentalmat#findfundamentalmat" target="_blank">findFundamentalMat</a>. There are several methods for recovering F there, linear and non-linear.<br />
However, H&amp;Z also point to a problem with using F right away &#8211; projective ambiguity. This means that the recovered camera matrices may not be the &#8220;real&#8221; ones, but instead have gone through some 3D projective transformation. To cope with this, we will use the <a href="http://en.wikipedia.org/wiki/Essential_matrix" target="_blank">Essential Matrix</a> instead, which is sort of the same thing (holds epiploar constraint over points) but for calibrated cameras. Using the Essential matrix removes the projective ambiguity and provides a Metric (or Singular) Reconstruction, which means the 3D points are true up to scaling alone, and not up to a projective transformation.</p>
<pre class="brush: plain; title: ; notranslate">
cv::FileStorage fs;
fs.open(&quot;camera_calibration.yml&quot;,cv::FileStorage::READ);
fs[&quot;camera_matrix&quot;]&gt;&gt;K;

Mat F = findFundamentalMat(imgpts1, imgpts2, FM_RANSAC, 0.1, 0.99, status);
Mat E = K.t() * F * K; //according to HZ (9.12)
</pre>
<p>Now let&#8217;s assume one camera is P = [I|0], meaning it hasn&#8217;t moved or rotated, getting the second camera matrix, P&#8217; = [R|t], is done as follows:</p>
<pre class="brush: plain; title: ; notranslate">
SVD svd(E);
Matx33d W(0,-1,0,	//HZ 9.13
	  1,0,0,
	  0,0,1);
Matx33d Winv(0,1,0,
	 -1,0,0,
	 0,0,1);
Mat_ R = svd.u * Mat(W) * svd.vt; //HZ 9.19
Mat_ t = svd.u.col(2); //u3
P1 = Matx34d(R(0,0),	R(0,1),	R(0,2),	t(0),
		 R(1,0),	R(1,1),	R(1,2),	t(1),
		 R(2,0),	R(2,1),	R(2,2), t(2));
</pre>
<p>Looks good, now let&#8217;s move on to reconstruction.</p>
<h2>Reconstruction via Triangulation</h2>
<p>Once we have two camera matrices, P and P&#8217;, we can recover the 3D structure of the scene. This can be seen simply if we think about it using ray intersection. We have two points in space of the camera centers (one in 0,0,0 and one in t), and we have the location in space of a point both on the image plane of image 1 and on the image plane of image 2. If we simply shoot a ray from from one camera center through the respective point and another ray from the other camera &#8211; the intersection of the two rays must be the real location of the object in space.<br />
In real life, none of that works. The rays usually will not intersect (so H&amp;Z refer to the mid-point algorithm, which they dismiss as a bad choice), and ray intersection in general is inferior to other triangulation methods.<br />
H&amp;Z go on to describe their &#8220;optimal&#8221; triangulation method, which optimizes the solution based on the error from reprojection of the points back to the image plane.<br />
I have implemented the linear triangulation methods they present, and wrote a post about it not long ago: <a title="http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/" href="http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/" target="_blank">Here</a>.<br />
I also added the Iterative Least Squares method that Hartley presented in his article &#8220;<a href="http://users.cecs.anu.edu.au/~hartley/Papers/triangulation/triangulation.pdf" target="_blank">Triangulation</a>&#8220;, which is said to perform very good and very fast.</p>
<div id="attachment_1056" class="wp-caption aligncenter" style="width: 333px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-1.22.59-AM.png" rel="lightbox[998]"><img class="size-full wp-image-1056" title="depth map" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-1.22.59-AM.png" alt="" width="323" height="263" /></a><p class="wp-caption-text">&quot;Depth Map&quot;</p></div>
<div id="attachment_1057" class="wp-caption aligncenter" style="width: 576px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-1.23.36-AM.png" rel="lightbox[998]"><img class="size-full wp-image-1057" title="reconstruction" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-1.23.36-AM.png" alt="" width="566" height="349" /></a><p class="wp-caption-text">3D reconstruction</p></div>
<p>A word of notice, many many times the reconstruction will fail because the Fundamental matrix came out wrong. The results will just look aweful, and nothing like a true reconstruction. To cope with this, you may want to insert a check that will make sure the two P matrices are not completely bogus (you could check for a reasonable rotation for example). If the P matrices, that are derived from the F matrix, are strange, then you can discard this F matrix and compute a new one.</p>
<div id="attachment_1063" class="wp-caption aligncenter" style="width: 330px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-06-at-6.42.02-PM.png" rel="lightbox[998]"><img class="size-full wp-image-1063" title="Bad reconstruction" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-06-at-6.42.02-PM.png" alt="" width="320" height="263" /></a><p class="wp-caption-text">Example of when things go bad...</p></div>
<h2>Toolbox and Framework</h2>
<p>I created a small toolbox of the various methods I spoke about in this post, and created a very simple UI. It basically allows you to load two images and then try the different methods on them and get the results.<br />
It&#8217;s using FLTK3 for the GUI, and PCL (VTK backend) for visualization of the result 3D point cloud.<br />
It also includes a few classes with a simple API that let&#8217;s you get the features matches, motion map, camera matrices from the motion, and finally the 3D point cloud.</p>
<div id="attachment_1055" class="wp-caption aligncenter" style="width: 525px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-1.10.47-AM.png" rel="lightbox[998]"><img class=" wp-image-1055  " title="SfM GUI" src="http://www.morethantechnical.com/wp-content/uploads/2012/02/Screen-shot-2012-02-05-at-1.10.47-AM.png" alt="" width="515" height="156" /></a><p class="wp-caption-text">FLTK GUI</p></div>
<h2>Code &amp; Where to go next</h2>
<p>The code, as usual, is up for grabs at github:</p>
<pre><a title="Github repo" href="https://github.com/royshil/SfM-Toy-Library" target="_blank">https://github.com/royshil/SfM-Toy-Library</a></pre>
<p>Now, that have a firm grasp of SfM <img src='http://www.morethantechnical.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' />  you can go on to visit the following projects, which implement a much more robust solution:</p>
<p><a title="http://phototour.cs.washington.edu/bundler/" href="http://phototour.cs.washington.edu/bundler/" target="_blank">http://phototour.cs.washington.edu/bundler/</a><br />
<a title="http://code.google.com/p/libmv/" href="http://code.google.com/p/libmv/" target="_blank">http://code.google.com/p/libmv/</a><br />
<a title="http://www.cs.washington.edu/homes/ccwu/vsfm/" href="http://www.cs.washington.edu/homes/ccwu/vsfm/" target="_blank">http://www.cs.washington.edu/homes/ccwu/vsfm/</a></p>
<p>And Wikipedia points to some interesting libraries and code as well: <a href="http://en.wikipedia.org/wiki/Structure_from_motion" target="_blank">http://en.wikipedia.org/wiki/Structure_from_motion</a></p>
<p>Enjoy!</p>
<p>Roy.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2012%2F02%2F07%2Fstructure-from-motion-and-3d-reconstruction-on-the-easy-in-opencv-2-3-w-code%2F&amp;title=Structure%20from%20Motion%20and%203D%20reconstruction%20on%20the%20easy%20in%20OpenCV%202.3%2B%20%5Bw%2F%20code%5D" id="wpa2a_2"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2012/02/07/structure-from-motion-and-3d-reconstruction-on-the-easy-in-opencv-2-3-w-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Simple triangulation with OpenCV from Harley &amp; Zisserman [w/ code]</title>
		<link>http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/</link>
		<comments>http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/#comments</comments>
		<pubDate>Wed, 04 Jan 2012 01:07:11 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[3d]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[school]]></category>
		<category><![CDATA[vision]]></category>
		<category><![CDATA[pcl]]></category>
		<category><![CDATA[reconstruction]]></category>
		<category><![CDATA[triangulation]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=1023</guid>
		<description><![CDATA[Easily using OpenCV 2.3+ to triangulate points from known camera matrices and point sets.]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2012/01/screenshot-1325526702.png" rel="lightbox[1023]"><img src="http://www.morethantechnical.com/wp-content/uploads/2012/01/screenshot-1325526702-150x150.png" alt="" title="Triangulated" width="150" height="150" class="alignleft size-thumbnail wp-image-1031" /></a>Hi<br />
I sense that a lot of people are looking for a simple triangulation method with OpenCV, when they have two images and matching features.<br />
While OpenCV contains the function cvTriangulatePoints in the triangulation.cpp file, it is not documented, and uses the arcane C API.<br />
Luckily, Hartley and Zisserman describe in their excellent book &#8220;Multiple View Geometry&#8221; (in many cases considered to be &#8220;The Bible&#8221; of 3D reconstruction), a simple method for linear triangulation. This method is actually discussed earlier in Hartley&#8217;s article &#8220;<a href="http://users.cecs.anu.edu.au/~hartley/Papers/triangulation/triangulation.pdf" target="_blank">Triangulation</a>&#8220;.<br />
I implemented it using the new OpenCV 2.3+ C++ API, which makes it super easy, and here it is before you.</p>
<p><span id="more-1023"></span></p>
<p>The thing about triangulation is that you need to know the extrinsic parameters of your cameras &#8211; the difference in location and rotation between them.<br />
To get the camera matrices&#8230; that&#8217;s a different story that I&#8217;m going to cover shortly in a tutorial (already in writing) about Structure from Motion.</p>
<p>But let&#8217;s assume that we already have the extrinsic matrices. In most cases, where you know what the motion is (you took the pictures <img src='http://www.morethantechnical.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> , you can just write the matrices explicitly.</p>
<h2>Linear Triangulation</h2>
<pre class="brush: plain; title: ; notranslate">
/**
 From &quot;Triangulation&quot;, Hartley, R.I. and Sturm, P., Computer vision and image understanding, 1997
 */
Mat_ LinearLSTriangulation(Point3d u,		//homogenous image point (u,v,1)
				   Matx34d P,		//camera 1 matrix
				   Point3d u1,		//homogenous image point in 2nd camera
				   Matx34d P1		//camera 2 matrix
								   )
{
	//build matrix A for homogenous equation system Ax = 0
	//assume X = (x,y,z,1), for Linear-LS method
	//which turns it into a AX = B system, where A is 4x3, X is 3x1 and B is 4x1
	Matx43d A(u.x*P(2,0)-P(0,0),	u.x*P(2,1)-P(0,1),		u.x*P(2,2)-P(0,2),
		  u.y*P(2,0)-P(1,0),	u.y*P(2,1)-P(1,1),		u.y*P(2,2)-P(1,2),
		  u1.x*P1(2,0)-P1(0,0), u1.x*P1(2,1)-P1(0,1),	u1.x*P1(2,2)-P1(0,2),
		  u1.y*P1(2,0)-P1(1,0), u1.y*P1(2,1)-P1(1,1),	u1.y*P1(2,2)-P1(1,2)
			  );
	Mat_ B = (Mat_(4,1) &lt;&lt;	-(u.x*P(2,3)	-P(0,3)),
					  -(u.y*P(2,3)	-P(1,3)),
					  -(u1.x*P1(2,3)	-P1(0,3)),
					  -(u1.y*P1(2,3)	-P1(1,3)));

	Mat_ X;
	solve(A,B,X,DECOMP_SVD);

	return X;
}
</pre>
<p>This method relies very simply on the principle that every 2D point in image plane coordinates is a projection of the real 3D point. So if you have two views, you can set up an overdetermined linear equation system to solve for the 3D position.</p>
<p>See how simple defining a Matx43d struct from scratch and using it in solve(..) is?<br />
I tried doing some more fancy stuff with Mat.row(i) and Mat.col(i), trying to stick to Hartley&#8217;s description of the A matrix, but it just didn&#8217;t work.</p>
<h2>Using it</h2>
<p>Using this method is easy:</p>
<pre class="brush: plain; title: ; notranslate">
//Triagulate points
void TriangulatePoints(const vector&amp; pt_set1,
					   const vector&amp; pt_set2,
					   const Mat&amp; Kinv,
					   const Matx34d&amp; P,
					   const Matx34d&amp; P1,
					   vector&amp; pointcloud,
					   vector&amp; correspImg1Pt)
{
#ifdef __SFM__DEBUG__
	vector depths;
#endif

	pointcloud.clear();
	correspImg1Pt.clear();

	cout &lt;&lt; &quot;Triangulating...&quot;;
	double t = getTickCount();
	unsigned int pts_size = pt_set1.size();
#pragma omp parallel for
	for (unsigned int i=0; i		Point2f kp = pt_set1[i];
		Point3d u(kp.x,kp.y,1.0);
		Mat_ um = Kinv * Mat_(u);
		u = um.at(0);
		Point2f kp1 = pt_set2[i];
		Point3d u1(kp1.x,kp1.y,1.0);
		Mat_ um1 = Kinv * Mat_(u1);
		u1 = um1.at(0);

		Mat_ X = IterativeLinearLSTriangulation(u,P,u1,P1);

//		if(X(2) &gt; 6 || X(2) &lt; 0) continue;

#pragma omp critical
		{
			pointcloud.push_back(Point3d(X(0),X(1),X(2)));
			correspImg1Pt.push_back(pt_set1[i]);
#ifdef __SFM__DEBUG__
			depths.push_back(X(2));
#endif
		}
	}
	t = ((double)getTickCount() - t)/getTickFrequency();
	cout &lt;&lt; &quot;Done. (&quot;&lt;
	//show &quot;range image&quot;
#ifdef __SFM__DEBUG__
	{
		double minVal,maxVal;
		minMaxLoc(depths, &amp;minVal, &amp;maxVal);
		Mat tmp(240,320,CV_8UC3); //cvtColor(img_1_orig, tmp, CV_BGR2HSV);
		for (unsigned int i=0; i			double _d = MAX(MIN((pointcloud[i].z-minVal)/(maxVal-minVal),1.0),0.0);
			circle(tmp, correspImg1Pt[i], 1, Scalar(255 * (1.0-(_d)),255,255), CV_FILLED);
		}
		cvtColor(tmp, tmp, CV_HSV2BGR);
		imshow(&quot;out&quot;, tmp);
		waitKey(0);
		destroyWindow(&quot;out&quot;);
	}
#endif
}
</pre>
<p>Note that you must have the camera matrix K (a 3&#215;3 matrix of the intrinsic parameters), or rather it&#8217;s inverse, noted here as Kinv.</p>
<h2>Results and some discussion</h2>
<p><a href="http://www.morethantechnical.com/wp-content/uploads/2012/01/ER_15_12_2011_06_06_23.jpg" rel="lightbox[1023]"><img class="wp-image-1026 " title="Left image" src="http://www.morethantechnical.com/wp-content/uploads/2012/01/ER_15_12_2011_06_06_23-300x225.jpg" alt="" width="240" height="180" /></a><a href="http://www.morethantechnical.com/wp-content/uploads/2012/01/ER_15_12_2011_06_06_35.jpg" rel="lightbox[1023]"><img class="wp-image-1027 " title="Right image" src="http://www.morethantechnical.com/wp-content/uploads/2012/01/ER_15_12_2011_06_06_35-300x225.jpg" alt="" width="240" height="180" /></a></p>
<div id="attachment_1031" class="wp-caption alignnone" style="width: 598px"><a href="http://www.morethantechnical.com/wp-content/uploads/2012/01/screenshot-1325526702.png" rel="lightbox[1023]"><img class=" wp-image-1031 " title="Triangulated" src="http://www.morethantechnical.com/wp-content/uploads/2012/01/screenshot-1325526702.png" alt="" width="588" height="360" /></a><p class="wp-caption-text">3D view of the triangulated point cloud</p></div>
<p>Notice how stuff is distorted in the 3D view&#8230; but this is not due projective ambiguity! as I am using the Essential Matrix to obtain the camera P matrices (cameras are calibrated). Hartley and Zisserman explain this in their book on page 258, and the reasons for projective ambiguity (and how to resolve it) on page 265. The distortion must be due to inaccurate point correspondence&#8230;  </p>
<p>The cool visualization is done using the excellent <a href="http://www.pointclouds.org" title="PCL" target="_blank">PCL</a> library.</p>
<h2>Iterative Linear Triangulation</h2>
<p>Hartley, in his article &#8220;Triangulation&#8221; describes another triangulation algorithm, an iterative one, which he reports to &#8220;perform substantially better than the [...] non-iterative linear methods&#8221;. It is, again, very easy to implement, and here it is:</p>
<pre class="brush: plain; title: ; notranslate">
/**
 From &quot;Triangulation&quot;, Hartley, R.I. and Sturm, P., Computer vision and image understanding, 1997
 */
Mat_&lt;double&gt; IterativeLinearLSTriangulation(Point3d u,	//homogenous image point (u,v,1)
											Matx34d P,			//camera 1 matrix
											Point3d u1,			//homogenous image point in 2nd camera
											Matx34d P1			//camera 2 matrix
											) {
	double wi = 1, wi1 = 1;
	Mat_&lt;double&gt; X(4,1);
	for (int i=0; i&lt;10; i++) { //Hartley suggests 10 iterations at most
		Mat_&lt;double&gt; X_ = LinearLSTriangulation(u,P,u1,P1);
		X(0) = X_(0); X(1) = X_(1); X(2) = X_(2); X_(3) = 1.0;

		//recalculate weights
		double p2x = Mat_&lt;double&gt;(Mat_&lt;double&gt;(P).row(2)*X)(0);
		double p2x1 = Mat_&lt;double&gt;(Mat_&lt;double&gt;(P1).row(2)*X)(0);

		//breaking point
		if(fabsf(wi - p2x) &lt;= EPSILON &amp;&amp; fabsf(wi1 - p2x1) &lt;= EPSILON) break;

		wi = p2x;
		wi1 = p2x1;

		//reweight equations and solve
		Matx43d A((u.x*P(2,0)-P(0,0))/wi,		(u.x*P(2,1)-P(0,1))/wi,			(u.x*P(2,2)-P(0,2))/wi,
				  (u.y*P(2,0)-P(1,0))/wi,		(u.y*P(2,1)-P(1,1))/wi,			(u.y*P(2,2)-P(1,2))/wi,
				  (u1.x*P1(2,0)-P1(0,0))/wi1,	(u1.x*P1(2,1)-P1(0,1))/wi1,		(u1.x*P1(2,2)-P1(0,2))/wi1,
				  (u1.y*P1(2,0)-P1(1,0))/wi1,	(u1.y*P1(2,1)-P1(1,1))/wi1,		(u1.y*P1(2,2)-P1(1,2))/wi1
				  );
		Mat_&lt;double&gt; B = (Mat_&lt;double&gt;(4,1) &lt;&lt;	-(u.x*P(2,3)	-P(0,3))/wi,
						  -(u.y*P(2,3)	-P(1,3))/wi,
						  -(u1.x*P1(2,3)	-P1(0,3))/wi1,
						  -(u1.y*P1(2,3)	-P1(1,3))/wi1
						  );

		solve(A,B,X_,DECOMP_SVD);
		X(0) = X_(0); X(1) = X_(1); X(2) = X_(2); X_(3) = 1.0;
	}
	return X;
}
</pre>
<p>(remember to define your EPSILON)<br />
This time he works iteratively in order to minimize the reprojection error of the reconstructed point to the original image coordinate, by weighting the linear equation system.</p>
<h2>Recap</h2>
<p>So we&#8217;ve seen how easy it is to implement these triangulation methods using OpenCV&#8217;s nice Matx### and Mat_<X> structs.<br />
Also solve(&#8230;,DECOMP_SVD) is very handy for overdetermined non-homogeneous linear equation systems.<br />
Watch out for my Structure from Motion tutorial coming up, which will be all about using OpenCV to get point correspondence from pairs of images, obtaining camera matrices and recovering dense depth.</p>
<p>If you are looking for more robust solutions for SfM and 3D reconstructions, see:<br />
<a href="http://phototour.cs.washington.edu/bundler/" title="http://phototour.cs.washington.edu/bundler/" target="_blank">http://phototour.cs.washington.edu/bundler/</a><br />
<a href="http://code.google.com/p/libmv/" title="http://code.google.com/p/libmv/" target="_blank">http://code.google.com/p/libmv/</a><br />
<a href="http://www.cs.washington.edu/homes/ccwu/vsfm/" title="http://www.cs.washington.edu/homes/ccwu/vsfm/" target="_blank">http://www.cs.washington.edu/homes/ccwu/vsfm/</a><br />
Enjoy,<br />
Roy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2012/01/04/simple-triangulation-with-opencv-from-harley-zisserman-w-code/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Spherical harmonics face relighting using OpenCV, OpenGL [w/ code]</title>
		<link>http://www.morethantechnical.com/2011/12/20/spherical-harmonics-face-relighting-using-opencv-opengl-w-code/</link>
		<comments>http://www.morethantechnical.com/2011/12/20/spherical-harmonics-face-relighting-using-opencv-opengl-w-code/#comments</comments>
		<pubDate>Tue, 20 Dec 2011 00:59:34 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[3d]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[school]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[vision]]></category>
		<category><![CDATA[glsl]]></category>
		<category><![CDATA[harmonics]]></category>
		<category><![CDATA[math]]></category>
		<category><![CDATA[recoloring]]></category>
		<category><![CDATA[relighting]]></category>
		<category><![CDATA[shaders]]></category>
		<category><![CDATA[spherical]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=948</guid>
		<description><![CDATA[Implementing a face image relighting algorithm using spherical harmonics, based on a paper written by Wang et al (2007).]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/12/Screen-shot-2011-12-19-at-8.13.27-PM.png" rel="lightbox[948]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/12/Screen-shot-2011-12-19-at-8.13.27-PM-300x130.png" alt="" title="Spherical harmonics face relighting" width="300" height="130" class="alignleft size-medium wp-image-1015" /></a>Hi!<br />
I&#8217;ve been working on implementing a face image relighting algorithm using spherical harmonics, one of the most elegant methods I&#8217;ve seen lately.<br />
I start up by aligning a face model with OpenGL to automatically get the canonical face normals, which brushed up my knowledge of GLSL. Then I continue to estimating real faces &#8220;spharmonics&#8221;, and relighting.</p>
<p>Let&#8217;s start!<br />
<span id="more-948"></span></p>
<h2>Some mathematical background</h2>
<p>Don&#8217;t worry, it wont hurt. much.</p>
<p>So Spherical Harmonics, were invented to numerically express a whole bunch of things in physics like gravity and magnetic fields. But they also became very useful for computer graphics as they are perfect for modelling light falling on a spherical body.</p>
<h3>But what ARE those mysterious spherical harmonics? </h3>
<p>The way I see it, they are a series of &#8220;modes&#8221; or &#8220;eigenvectors&#8221; or &#8220;orthogonal components&#8221; of a base that spans the surface of a sphere.<br />
To put it simple, they describe the surface of a sphere in increasing finer grained portions. Much like a Fourier decomposition does to a function, there is the base and there are coefficients that when multiplied with the base they recover the function.</p>
<h3>How is that good for graphics? </h3>
<p>People have used spherical harmonics mostly to model lighting of spherical objects. When you know the coefficients that describe the lighting, you can change them to <i>Re-light</i> an object, or <i>De-light</i>, or transfer the lighting conditions of one scene to another. Very useful!</p>
<p>Some good researchers, Basri and Jacobs, back in 2001 have formulated the first 9 harmonics as a function of the surface normal. On this page Basri references all his work on the subject: <a href="http://www.wisdom.weizmann.ac.il/~ronen/index_files/harmonic.html" target="_blank">http://www.wisdom.weizmann.ac.il/~ronen/index_files/harmonic.html</a> </p>
<p>But I like to reference a work that&#8217;s easier to process than Basri&#8217;s, that is the work of Wang et al from 2007. These guys made the steps to use spherical harmonics easier to follow: <a href="http://research.microsoft.com/en-us/um/people/zliu/cvpr2007.pdf" title="http://research.microsoft.com/en-us/um/people/zliu/cvpr2007.pdf" target="_blank">http://research.microsoft.com/en-us/um/people/zliu/cvpr2007.pdf</a>.<br />
But their algorithm is quite advanced, as it solves not only for the harmonics&#8217; coefficients but also for the normals of the object in the image. They use some fancy optimization of an energy function over a graph, that I&#8217;m not going to discuss.<br />
But they did make the process of finding the spherical harmonics&#8217; coefficient very clear.</p>
<h4>The bottom line</h4>
<p>We should solve for a vector of 9 coefficients that describes the &#8220;lighting of the object&#8221; (a face in our case).<br />
Each coefficient will tell us how much that specific harmonic is strong or weak, or in other words how lit is that certain area of the object.</p>
<p>Wang and Basri show a very simple method of using simultaneous linear equations to solve for the lighting coefficients, it depends only on knowing the normal of the object&#8217;s surface at each pixel in the image.</p>
<h2>Getting the normals of a canonical face</h2>
<p>So to get the normals, I thought the best way is to use a canonical model of a face (some king of an average face), instead of trying to recover the normals from the image pixels.<br />
For that end, I used Rhino3D to model (very roughly) a shape that resembles a human face, starting from an elongated sphere.<br />
Now all that&#8217;s left is to align the model with the face to relight, and that will supply the normals.<br />
<a href="http://www.morethantechnical.com/wp-content/uploads/2011/12/snapshot00.png" rel="lightbox[948]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/12/snapshot00-300x224.png" alt="" title="rough model of a human face" width="300" height="224" class="alignleft size-medium wp-image-1011" /></a><br />
Cool. Then I built a small app that allows the user to move the model around until it&#8217;s aligned with the face image. I used <a href="http://www.fltk.org/" target="_blank">FLTK 3.0</a> to do it since they have a simple interface with OpenGL, they are cross platform, and lightweight.<br />
So I set up a scene where I have the image as the background, and the model is floating above it, half transparent so the user can find the right spot. I added functions for rotating the model, and extra stuff like turning the model opaque.</p>
<p style="text-align: center">
<iframe width="480" height="360" src="http://www.youtube.com/embed/wIwAX2UM64E" frameborder="0" allowfullscreen></iframe>
</p>
<p>To get the normal map I used a very simple GLSL shader, that simply colors the pixel with the value of the normal nX,nY,nZ -> R,G,B.<br />
This way the result image OpenGL renders is simply the normal map of the face model. I just grab it using glReadPixels.</p>
<h2>Estimating spherical harmonics</h2>
<p>So, after the model is aligned, we can assume we have the normals ready for us for each pixel in the image, and the intensity in each pixel is also known.<br />
The first step that Wang suggests, without knowledge of the real face albedo (the real color of every pixel without any lighting effect), is to get an approximation of the 9-vector of lighting coefficients by setting a constant albedo. Easy enough, we can set the albedo to the average color in the face.<br />
Then we can simply build a huge set of linear equations (huge as the number of pixels in the image), and solve an overdetermined system to get the 9 coefficients.</p>
<pre class="brush: plain; title: ; notranslate">
		Scalar albedo_constant = mean(face_img_hsv, smallFaceMask);

		//setup linear equation system, lighting coefficients (l) is unknown
		//I = p00 * Ht * l
		float p00 = (float)albedo_constant[2] / 255.0f;

		cout &lt;&lt; &quot;Build Ht(&quot;&lt;&lt;n&lt;&lt;&quot;,9)...&quot;;
		cout &lt;&lt; &quot;Build I(&quot;&lt;&lt;n&lt;&lt;&quot;,1)...&quot;;
		//build Ht and I
		Mat_&lt;float&gt; Ht(n,9);
		Mat_&lt;float&gt; I(n,1);
		int pos = 0;
		vector&lt;Mat_&lt;uchar&gt; &gt; face_img_chnls; split(face_img_hsv, face_img_chnls);
		for (int i=0; i&lt;normalMapFlat.rows; i++) {
			if (smallFaceMask(i) == 0) { //is this pixel on the face?
				continue;
			}
			Ht.row(pos) = p00 * calculateSphericalHarmonicsForNormal(normalMapFlat(i));
			I(pos,0) = face_img_chnls[2](i) / 255.0f; //get V from HSV of pixel [0,1]
			pos ++;
		}
		cout &lt;&lt; &quot;DONE&quot;  &lt;&lt; endl;

		cout &lt;&lt; &quot;Solve&quot; &lt;&lt;endl;
		solve(Ht, I, l, DECOMP_SVD);

		cout &lt;&lt; &quot;initial lighting coeffs: &quot;;
		for (int i=0; i&lt;l.rows; i++) {
			cout&lt;&lt;l.at&lt;float&gt;(i)&lt;&lt;&quot;,&quot;;
		}
</pre>
<p>Booyah! lighting coefficients.</p>
<p>But this is only the first step. Now we can get an approximation of the albedo as well, using the coefficients:</p>
<pre class="brush: plain; title: ; notranslate">
		Mat_&lt;Vec3b&gt; face_img_v3b = face_img;

		#pragma omp parallel for schedule(dynamic)
		for (int y=0; y&lt;face_img.rows; y++) {
			for (int x=0; x&lt;face_img.cols; x++) {
				if (face_mask(y,x) == 0) {
					albedo(y,x) = 0;
					continue;
				}
				Mat sph = calculateSphericalHarmonicsForNormal(normalMap(y,x));
				Mat_&lt;float&gt; sph_l = sph * l;
				float fsph_l = sph_l(0);

				for (int cn = 0; cn&lt;3; cn++) {
					float fimg = face_img_v3b(y,x)[cn] / 255.0f;
					albedo(y,x)[cn] = (fimg / fsph_l);
				}
			}
		}
</pre>
<p>Done.<br />
Now that we have an initial albedo, Wang suggests we compute the coefficients again to get a better approximation, and then the albedo again.<br />
I however ran into some problems trying to do the second iteration, and the results always came out too dark&#8230; But even with the first iteration you can see a very nice change.<br />
Look at the video from before, you can see the right side of the face, which is over-lit, was darkened and the left side was lit up.</p>
<h2>Code</h2>
<p>The code for spherical harmonics analysis of images is part of a bigger project I have been working on for some time. I also spoke of it in a <a href="http://www.morethantechnical.com/2011/12/01/identity-transfer-in-photographs/" target="_blank">previous post</a>.<br />
Anyway it&#8217;s up in GitHub: <a href="https://github.com/royshil/HeadReplacement/tree/master/HeadReplacement" target="_blank">https://github.com/royshil/HeadReplacement/tree/master/HeadReplacement</a><br />
You&#8217;re looking for 4 files:</p>
<ul>
<li>SpharmonicsUI.cpp
<li>SpharmonicsUI.h
<li>spherical_harmonics_analysis.cpp
<li>spherical_harmonics_analysis.h
</ul>
<p>You can use the CMakeLists.txt to compile, but here&#8217;s a CMakeLists.txt that should take you there in one piece (fingers crossed):</p>
<pre class="brush: plain; title: ; notranslate">
find_package(OpenCV REQUIRED)
find_package(OpenGL REQUIRED)
find_package(OpenMP REQUIRED)

######## Find and add GLEE ########
file(GLOB_RECURSE GLEE_PATH &quot;${CMAKE_SOURCE_DIR}/GLee.c&quot;)
if(GLEE_PATH STREQUAL GLEE_PATH-NOTFOUND)
	message(STATUS &quot;GLEE was not found&quot;)
else()
	list(LENGTH GLEE_PATH GLEE_PATH_LEN)
	if(GLEE_PATH_LEN GREATER 1)
		list(GET GLEE_PATH 1 GLEE_PATH)
	endif()
	file(RELATIVE_PATH GLEE_PATH ${CMAKE_SOURCE_DIR} ${GLEE_PATH})
	get_filename_component(GLEE_PATH ${GLEE_PATH} REALPATH)
	get_filename_component(GLEE_PATH ${GLEE_PATH} PATH)
	message(STATUS &quot;Found GLEE at ${GLEE_PATH}&quot;)
	add_library(GLEE ${GLEE_PATH}/GLee.c)
endif()

############ Find FLTK ############
if(NOT DEFINED FLTK_PATH)
	file(GLOB_RECURSE FLTK_PATH &quot;${CMAKE_SOURCE_DIR}/Widget.h&quot;)
	if(FLTK_PATH STREQUAL FLTK_PATH-NOTFOUND   OR   FLTK_PATH STREQUAL &quot;&quot;)
		message(STATUS &quot;FLTK was not found !!!!!&quot;)
	else()
		list(LENGTH FLTK_PATH FLTK_PATH_LEN)
		if(FLTK_PATH_LEN GREATER 1)
			list(GET FLTK_PATH 1 FLTK_PATH)
		endif()
		file(RELATIVE_PATH FLTK_PATH ${CMAKE_SOURCE_DIR} ${FLTK_PATH})
		get_filename_component(FLTK_PATH ${FLTK_PATH} REALPATH)
		get_filename_component(FLTK_PATH ${FLTK_PATH} PATH)
		message(STATUS &quot;Found FLTK at ${FLTK_PATH}&quot;)
	endif()
else()
	get_filename_component(FLTK_PATH ${FLTK_PATH} REALPATH)
	message(STATUS &quot;FLTK path set to ${FLTK_PATH}&quot;)
endif()
set(FLTK_INCLUDE_DIR ${FLTK_PATH}/include)
set(FLTK_LIB_DIR ${FLTK_PATH}/lib)

######## Relighting #######
include_directories(${FLTK_INCLUDE_DIR})
include_directories(${OpenGL_INCLUDE_DIRS})
include_directories(${GLEE_PATH})
add_library(VirtualSurgeon_Relighting
	../HeadReplacement/glm.cpp
	../HeadReplacement/spherical_harmonics_analysis.cpp
	../HeadReplacement/LaplacianBlending.cpp
	../HeadReplacement/SpharmonicsUI.cpp
	../HeadReplacement/OGL_OCV_common.cpp
	)
</pre>
<p>Note that I had to resort to some very dark magic to recover the location of FLTK and GLEE&#8230; But it&#8217;s a jungle out there.</p>
<p>The source of the photograph is: <a href="http://www.flickr.com/photos/roel1943/309048020/" target="_blank">http://www.flickr.com/photos/roel1943/309048020/</a><br />
It is released under Creative Commons 2.0 ShareAlike-Attribution. So all the results here are also CC-2.0-SA-A&#8230; <img src='http://www.morethantechnical.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Enjoy,<br />
Roy.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/12/20/spherical-harmonics-face-relighting-using-opencv-opengl-w-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>A Kinect browser plugin with FireBreath [w/ code]</title>
		<link>http://www.morethantechnical.com/2011/12/02/a-kinect-browser-plugin-with-firebreath-w-code/</link>
		<comments>http://www.morethantechnical.com/2011/12/02/a-kinect-browser-plugin-with-firebreath-w-code/#comments</comments>
		<pubDate>Fri, 02 Dec 2011 14:17:58 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[browser]]></category>
		<category><![CDATA[kinect]]></category>
		<category><![CDATA[plugin]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=996</guid>
		<description><![CDATA[Hi, Just reporting on a small achievement, part of a big project: Creating a browser plugin to display the Kinect depth map on screen. The integration was fairly easy, which leads me to think that both FireBreath and OpenNI/Nite are pretty neat framework that are robust.. So let&#8217;s see how it&#8217;s done From a template [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/12/Screen-shot-2011-12-02-at-9.12.03-AM.png" rel="lightbox[996]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/12/Screen-shot-2011-12-02-at-9.12.03-AM-150x150.png" alt="" title="Screen shot 2011-12-02 at 9.12.03 AM" width="150" height="150" class="alignleft size-thumbnail wp-image-1006" /></a>Hi,<br />
Just reporting on a small achievement, part of a big project: Creating a browser plugin to display the Kinect depth map on screen.<br />
The integration was fairly easy, which leads me to think that both FireBreath and OpenNI/Nite are pretty neat framework that are robust..<br />
So let&#8217;s see how it&#8217;s done<br />
<span id="more-996"></span></p>
<h2>From a template FireBreath plugin to an OpenGL plugin</h2>
<p>FireBreath is kind of an amazing project. They aim to be able to write a single source that will create plugins for all browsers and all operating systems. A daunting feat by my book. But building a MacOS Safari/Firefox plugin using their framework proved very simple&#8230;<br />
So I started here: <a href="http://www.firebreath.org/display/documentation/Mac+Video+Tutorial">http://www.firebreath.org/display/documentation/Mac+Video+Tutorial</a><br />
It&#8217;s a video tutorial of how to create a plugin from template, build it, install it and run it. Follow their instructions and you&#8217;ll have your plugin ready in 10 minutes.<br />
The next step will be to make our plugin display an OpenGL scene, which is what OpenNI/NITE use to display their depth map. This was also easy, borrowing code from the <a href="http://www.firebreath.org/display/documentation/OpenGL+Plugin">FireBreath OpenGL example</a>.<br />
However I ended up with a smaller source since I threw away most of the stuff&#8230;</p>
<pre class="brush: plain; title: ; notranslate">
class tutorialpluginMac : public tutorialplugin {
public:
    tutorialpluginMac();
	~tutorialpluginMac();

    BEGIN_PLUGIN_EVENT_MAP()
	EVENTTYPE_CASE(FB::AttachedEvent, onWindowAttached, FB::PluginWindowMac)
	EVENTTYPE_CASE(FB::DetachedEvent, onWindowDetached, FB::PluginWindowMac)
	PLUGIN_EVENT_MAP_CASCADE(tutorialplugin)
    END_PLUGIN_EVENT_MAP()

    virtual bool onWindowAttached(FB::AttachedEvent *evt, FB::PluginWindowMac*);
    virtual bool onWindowDetached(FB::DetachedEvent *evt, FB::PluginWindowMac*);
protected:

private:
    void* m_layer;

};

void glutDisplay (void); //this is implemented in the NITE code

@interface MyCAOpenGLLayer : CAOpenGLLayer {
    GLfloat m_angle;
}
@end

@implementation MyCAOpenGLLayer

- (id) init {
    if ([super init]) {
        m_angle = 0;
    }
    return self;
}

- (void)drawInCGLContext:(CGLContextObj)ctx pixelFormat:(CGLPixelFormatObj)pf forLayerTime:(CFTimeInterval)t displayTime:(const CVTimeStamp *)ts {
    //m_angle += 1;
    GLsizei width = CGRectGetWidth([self bounds]), height = CGRectGetHeight([self bounds]);
    GLfloat halfWidth = width / 2, halfHeight = height / 2;

    glViewport(0, 0, width, height);

	glutDisplay(); //let NITE draw it's stuff

    [super drawInCGLContext:ctx pixelFormat:pf forLayerTime:t displayTime:ts];
}

@end

tutorialpluginMac::tutorialpluginMac() : m_layer(NULL) {}

tutorialpluginMac::~tutorialpluginMac()
{
    if (m_layer) {
        [(CALayer*)m_layer removeFromSuperlayer];
        [(CALayer*)m_layer release];
        m_layer = NULL;
    }
}

bool tutorialpluginMac::onWindowAttached(FB::AttachedEvent* evt, FB::PluginWindowMac* wnd)
{
	cout &lt;&lt; &quot;tutorialpluginMac::onWindowAttached&quot; &lt;&lt; endl;
    if (FB::PluginWindowMac::DrawingModelCoreAnimation == wnd-&gt;getDrawingModel() ||
		FB::PluginWindowMac::DrawingModelInvalidatingCoreAnimation == wnd-&gt;getDrawingModel())
	{
        cout &lt;&lt; &quot; Setup CAOpenGL drawing. &quot;&lt;&lt;endl;
        MyCAOpenGLLayer* layer = [MyCAOpenGLLayer new];
        layer.asynchronous = (FB::PluginWindowMac::DrawingModelInvalidatingCoreAnimation == wnd-&gt;getDrawingModel()) ? NO : YES;
        layer.autoresizingMask = kCALayerWidthSizable | kCALayerHeightSizable;
        layer.needsDisplayOnBoundsChange = YES;
        m_layer = layer;
        if (FB::PluginWindowMac::DrawingModelInvalidatingCoreAnimation == wnd-&gt;getDrawingModel())
            wnd-&gt;StartAutoInvalidate(1.0/30.0);
        [(CALayer*) wnd-&gt;getDrawingPrimitive() addSublayer:layer];
    }
    return tutorialplugin::onWindowAttached(evt,wnd);
}

bool tutorialpluginMac::onWindowDetached(FB::DetachedEvent* evt, FB::PluginWindowMac* wnd)
{
    return tutorialplugin::onWindowDetached(evt,wnd);
}
</pre>
<p>(You guys will have to fill in the gaps&#8230; includes, etc.)</p>
<p>This goes in a new file, a new subclass of the generic plugin, only for Mac. For windows, you should subclass again and create the OpenGL context using WIN32 API or equivalent.</p>
<p>CMakeLists.txt files are also affected. Check out the repo.</p>
<h2>NITE OpenGL rendering</h2>
<p>Now that the plugin will just draw whatever NITE is drawing, half the battle is done. So for the drawing code I took the simple NiPointViewer example from the NITE library (get it <a href="http://www.openni.org/">here</a>).<br />
But, since we have need no windows management in the OpenNI, again we can make everything more simple. I took the code exactly as it is, and changed really just a small bit.<br />
I added<br />
<code><br />
#undef USE_GLUT<br />
#undef USE_GLES<br />
</code>, which pretty much makes that code compile to a very lean code (without window management etc.).<br />
And I rescued the glOrtho call in glutDisplay()<br />
<code><br />
//#ifdef USE_GLUT<br />
	glOrtho(0, mode.nXRes, mode.nYRes, 0, -1.0, 1.0);<br />
#if defined(USE_GLES)<br />
	glOrthof(0, mode.nXRes, mode.nYRes, 0, -1.0, 1.0);<br />
#endif<br />
</code></p>
<p>But the rest is pretty much identical.</p>
<p>One more thing, we should start the Kinect driver and OpenNI stack from somewhere in the plugin loading steps. In the main.cpp file from NITE I changed the main() function to kinect_main().<br />
I did that by adding it here, in the generic plugin (not the Mac subclass because it should be called from all OSs):</p>
<pre class="brush: plain; title: ; notranslate">
bool tutorialplugin::onWindowAttached(FB::AttachedEvent *evt, FB::PluginWindow *)
{
    // The window is attached; act appropriately
	kinect_main(0, 0);
	cout &lt;&lt; &quot;tutorialplugin::onWindowAttached&quot; &lt;&lt; endl;
    return true;
}
</pre>
<p>It now will fire when a window is attached to the plugin. The OpenGL calls will start running after the OGL context is up and starts rendering in a loop.</p>
<h2>Source and stuff</h2>
<p>Get the source for the Kinect-FireBreath plugin at GitHub: <a href="https://github.com/royshil/KinectPlugin">https://github.com/royshil/KinectPlugin</a></p>
<p>This is how it looks:<br />
<a style="display:block;" href="http://www.morethantechnical.com/wp-content/uploads/2011/12/Screen-shot-2011-12-02-at-9.12.03-AM.png" rel="lightbox[996]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/12/Screen-shot-2011-12-02-at-9.12.03-AM.png" alt="" title="Screen shot 2011-12-02 at 9.12.03 AM" width="341" height="462" class="alignleft size-full wp-image-1006" /></a></p>
<p>Cool.<br />
Roy</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F12%2F02%2Fa-kinect-browser-plugin-with-firebreath-w-code%2F&amp;title=A%20Kinect%20browser%20plugin%20with%20FireBreath%20%5Bw%2F%20code%5D" id="wpa2a_4"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/12/02/a-kinect-browser-plugin-with-firebreath-w-code/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Identity Transfer in Photographs</title>
		<link>http://www.morethantechnical.com/2011/12/01/identity-transfer-in-photographs/</link>
		<comments>http://www.morethantechnical.com/2011/12/01/identity-transfer-in-photographs/#comments</comments>
		<pubDate>Thu, 01 Dec 2011 05:29:58 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[school]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[vision]]></category>
		<category><![CDATA[head]]></category>
		<category><![CDATA[identity]]></category>
		<category><![CDATA[images]]></category>
		<category><![CDATA[photographs]]></category>
		<category><![CDATA[replacement]]></category>
		<category><![CDATA[survey]]></category>
		<category><![CDATA[transfer]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=1000</guid>
		<description><![CDATA[Hi! I would like to present something I have been working on recently, a work that immensely affect what I wrote in the blog in the past two years&#8230; To use it: Go on this page, Watch the short instruction video, download the application (MacOSX-Intel-x64 Win32) and make yourself a model! It takes just a [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/12/male_model.jpg" rel="lightbox[1000]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/12/male_model-150x150.jpg" alt="" title="male_model" width="150" height="150" class="alignleft size-thumbnail wp-image-1001" /></a>Hi!</p>
<p>I would like to present something I have been working on recently, a work that immensely affect what I wrote in the blog in the past two years&#8230;</p>
<p>To use it:<br />
Go on this <a href="http://palimpost.xvm.mit.edu/HeadReplacement/default.html">page</a>,<br />
Watch the short <a href="http://youtu.be/YhHb3FAqaUk">instruction video</a>,<br />
download the application (<a href="http://palimpost.xvm.mit.edu/HeadReplacement/bin/HeadReplacement.dmg">MacOSX-Intel-x64</a> <a href="http://palimpost.xvm.mit.edu/HeadReplacement/bin/HeadReplacement_win32.zip">Win32</a>)<br />
and make yourself a model!<br />
It takes just a couple of minutes and it&#8217;s very simple&#8230;</p>
<p>This work is an academic research project, Please please, take the time to fill out the <a href="https://docs.google.com/spreadsheet/viewform?formkey=dGNBX0ljZXRVXzdtbjBQZ0dULTQwelE6MQ">survey</a>! It is very short..<br />
The results of the <a href="https://docs.google.com/spreadsheet/viewform?formkey=dGNBX0ljZXRVXzdtbjBQZ0dULTQwelE6MQ">survey</a> (the survey alone, no photos of your work) will possibly be published in an academic paper.</p>
<p>Note: No information is sent anywhere in any way outside of your machine (you may even unplug the network). All results are saved locally on your computer, and no inputs are recorded or transmitted. The application contains no malware. The source is available here.</p>
<p>Note II: All stock photos of models used in the application are released under Creative Commons By-NC-SA 2.0 license. Creator: http://www.flickr.com/photos/kk/. If you wish to distribute your results, they should also be released under a CC-By-NC-SA 2.0 license.</p>
<p>Thank you!<br />
Roy.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F12%2F01%2Fidentity-transfer-in-photographs%2F&amp;title=Identity%20Transfer%20in%20Photographs" id="wpa2a_6"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/12/01/identity-transfer-in-photographs/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Just a simple Laplacian pyramid blender using OpenCV [w/code]</title>
		<link>http://www.morethantechnical.com/2011/11/13/just-a-simple-laplacian-pyramid-blender-using-opencv-wcode/</link>
		<comments>http://www.morethantechnical.com/2011/11/13/just-a-simple-laplacian-pyramid-blender-using-opencv-wcode/#comments</comments>
		<pubDate>Sun, 13 Nov 2011 07:39:47 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[blend]]></category>
		<category><![CDATA[blending]]></category>
		<category><![CDATA[laplacian]]></category>
		<category><![CDATA[pyramids]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=962</guid>
		<description><![CDATA[I want to share a small piece of code to do Laplacian Blending using OpenCV. It&#8217;s one of the most basic and canonical methods of image blending, and is a must exercise for any computer graphics student. Well basically it&#8217;s a matter of creating two Laplacian pyramids of both images, and a Gaussian pyramid of [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/11/Screen-shot-2011-11-13-at-2.37.49-AM.png" rel="lightbox[962]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/11/Screen-shot-2011-11-13-at-2.37.49-AM-150x150.png" alt="" title="OrangApple" width="150" height="150" class="alignleft size-thumbnail wp-image-992" /></a>I want to share a small piece of code to do Laplacian Blending using OpenCV. It&#8217;s one of the most basic and canonical methods of image blending, and is a must exercise for any computer graphics student.<br />
<span id="more-962"></span><br />
Well basically it&#8217;s a matter of creating two Laplacian pyramids of both images, and a Gaussian pyramid of the mask.<br />
Then we blend the pyramids into one, and collapse the resulting pyramid into the blended image.</p>
<pre class="brush: plain; title: ; notranslate">
#include &quot;opencv2/opencv.hpp&quot;

using namespace cv;

class LaplacianBlending {
private:
	Mat_&lt;Vec3f&gt; left;
	Mat_&lt;Vec3f&gt; right;
	Mat_&lt;float&gt; blendMask;

	vector&lt;Mat_&lt;Vec3f&gt; &gt; leftLapPyr,rightLapPyr,resultLapPyr;
	Mat leftSmallestLevel, rightSmallestLevel, resultSmallestLevel;
	vector&lt;Mat_&lt;Vec3f&gt; &gt; maskGaussianPyramid; //masks are 3-channels for easier multiplication with RGB

	int levels;

	void buildPyramids() {
		buildLaplacianPyramid(left,leftLapPyr,leftSmallestLevel);
		buildLaplacianPyramid(right,rightLapPyr,rightSmallestLevel);
		buildGaussianPyramid();
	}

	void buildGaussianPyramid() {
		assert(leftLapPyr.size()&gt;0);

		maskGaussianPyramid.clear();
		Mat currentImg;
		cvtColor(blendMask, currentImg, CV_GRAY2BGR);
		maskGaussianPyramid.push_back(currentImg); //highest level

		currentImg = blendMask;
		for (int l=1; l&lt;levels+1; l++) {
			Mat _down;
			if (leftLapPyr.size() &gt; l) {
				pyrDown(currentImg, _down, leftLapPyr[l].size());
			} else {
				pyrDown(currentImg, _down, leftSmallestLevel.size()); //smallest level
			}

			Mat down;
			cvtColor(_down, down, CV_GRAY2BGR);
			maskGaussianPyramid.push_back(down);
			currentImg = _down;
		}
	}

	void buildLaplacianPyramid(const Mat&amp; img, vector&lt;Mat_&lt;Vec3f&gt; &gt;&amp; lapPyr, Mat&amp; smallestLevel) {
		lapPyr.clear();
		Mat currentImg = img;
		for (int l=0; l&lt;levels; l++) {
			Mat down,up;
			pyrDown(currentImg, down);
			pyrUp(down, up, currentImg.size());
			Mat lap = currentImg - up;
			lapPyr.push_back(lap);
			currentImg = down;
		}
		currentImg.copyTo(smallestLevel);
	}

	Mat_&lt;Vec3f&gt; reconstructImgFromLapPyramid() {
		Mat currentImg = resultSmallestLevel;
		for (int l=levels-1; l&gt;=0; l--) {
			Mat up;

			pyrUp(currentImg, up, resultLapPyr[l].size());
			currentImg = up + resultLapPyr[l];
		}
		return currentImg;
	}

	void blendLapPyrs() {
		resultSmallestLevel = leftSmallestLevel.mul(maskGaussianPyramid.back()) +
									rightSmallestLevel.mul(Scalar(1.0,1.0,1.0) - maskGaussianPyramid.back());
		for (int l=0; l&lt;levels; l++) {
			Mat A = leftLapPyr[l].mul(maskGaussianPyramid[l]);
			Mat antiMask = Scalar(1.0,1.0,1.0) - maskGaussianPyramid[l];
			Mat B = rightLapPyr[l].mul(antiMask);
			Mat_&lt;Vec3f&gt; blendedLevel = A + B;

			resultLapPyr.push_back(blendedLevel);
		}
	}

public:
	LaplacianBlending(const Mat_&lt;Vec3f&gt;&amp; _left, const Mat_&lt;Vec3f&gt;&amp; _right, const Mat_&lt;float&gt;&amp; _blendMask, int _levels):
	left(_left),right(_right),blendMask(_blendMask),levels(_levels)
	{
		assert(_left.size() == _right.size());
		assert(_left.size() == _blendMask.size());
		buildPyramids();
		blendLapPyrs();
	};

	Mat_&lt;Vec3f&gt; blend() {
		return reconstructImgFromLapPyramid();
	}
};

Mat_&lt;Vec3f&gt; LaplacianBlend(const Mat_&lt;Vec3f&gt;&amp; l, const Mat_&lt;Vec3f&gt;&amp; r, const Mat_&lt;float&gt;&amp; m) {
	LaplacianBlending lb(l,r,m,4);
	return lb.blend();
}
</pre>
<p>To use, simply call the function LaplacianBlend with your two images and your mask, and the result will be returned.<br />
Here&#8217;s something I did with it:<br />
<a href="http://www.morethantechnical.com/wp-content/uploads/2011/11/Screen-shot-2011-11-13-at-2.35.01-AM.png" rel="lightbox[962]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/11/Screen-shot-2011-11-13-at-2.35.01-AM.png" alt="" title="Laplacian blending" width="851" height="254" class="alignleft size-full wp-image-991" /></a></p>
<p>Enjoy<br />
Roy.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F11%2F13%2Fjust-a-simple-laplacian-pyramid-blender-using-opencv-wcode%2F&amp;title=Just%20a%20simple%20Laplacian%20pyramid%20blender%20using%20OpenCV%20%5Bw%2Fcode%5D" id="wpa2a_8"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/11/13/just-a-simple-laplacian-pyramid-blender-using-opencv-wcode/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>A GLSL shader showing the normal map [w/ code]</title>
		<link>http://www.morethantechnical.com/2011/10/30/a-glsl-shader-showing-the-normal-map-w-code/</link>
		<comments>http://www.morethantechnical.com/2011/10/30/a-glsl-shader-showing-the-normal-map-w-code/#comments</comments>
		<pubDate>Sun, 30 Oct 2011 15:16:55 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[3d]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Solutions]]></category>
		<category><![CDATA[fragment]]></category>
		<category><![CDATA[glsl]]></category>
		<category><![CDATA[normal]]></category>
		<category><![CDATA[shader]]></category>
		<category><![CDATA[vertex]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=958</guid>
		<description><![CDATA[A very simple thing, although I couldn&#8217;t find on Google some place to copy-paste off, so here it is: Vertex shader Fragment shader A technique to load the shaders that will save you a lot of headaches I based it on this example from NeHe. It does periodical error checking so you can see if [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/10/Screen-shot-2011-10-30-at-11.13.48-AM.png" rel="lightbox[958]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/10/Screen-shot-2011-10-30-at-11.13.48-AM-150x150.png" alt="" title="Screen shot 2011-10-30 at 11.13.48 AM" width="150" height="150" class="alignleft size-thumbnail wp-image-963" /></a><a href="http://www.morethantechnical.com/wp-content/uploads/2011/10/Screen-shot-2011-10-30-at-11.13.54-AM.png" rel="lightbox[958]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/10/Screen-shot-2011-10-30-at-11.13.54-AM-150x150.png" alt="" title="Screen shot 2011-10-30 at 11.13.54 AM" width="150" height="150" class="alignleft size-thumbnail wp-image-964" /></a><br />
A very simple thing, although I couldn&#8217;t find on Google some place to copy-paste off, so here it is:<br />
<span id="more-958"></span></p>
<h3>Vertex shader</h3>
<pre class="brush: plain; title: ; notranslate">
varying vec3 normal;

void main()
{
    gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
    normal = gl_NormalMatrix * gl_Normal;
}
</pre>
<h3>Fragment shader</h3>
<pre class="brush: plain; title: ; notranslate">
varying vec3 normal;

void main()
{
    vec3 normal_normal = normalize(normal);
	gl_FragColor = vec4(normal_normal, 1.0);
}
</pre>
<h3>A technique to load the shaders that will save you a lot of headaches</h3>
<pre class="brush: plain; title: ; notranslate">
GLvoid* my_program;

//Error-checking function
void checkARBError(GLvoid* obj) {
	char infolog[1024] = {0}; int _written = 0;
	glGetInfoLogARB(obj, 1024, &amp;_written, infolog);
	if(_written&gt;0) {
		cerr &lt;&lt; infolog &lt;&lt; endl;
	}
}	

bool notIsAscii(int i) { return !isascii(i); }

void init_shaders() {
	const GLubyte* lang_ver = glGetString(GL_SHADING_LANGUAGE_VERSION);
	cout &lt;&lt;&quot;shading language version: &quot;&lt;&lt;(uchar*)lang_ver&lt;&lt;endl;

	const char * my_fragment_shader_source;
	const char * my_vertex_shader_source;

        //Reading shaders from files
	ifstream ifs(&quot;vshader.txt&quot;);
	ostringstream ss; ss &lt;&lt; ifs.rdbuf();
	ifstream ifs1(&quot;fshader.txt&quot;);
	ostringstream ss1; ss1 &lt;&lt; ifs1.rdbuf();
	ifs.close(); ifs1.close();

        //Cleaning up the strings...
	string _vertex = ss.str(); _vertex.erase(remove_if(_vertex.begin(), _vertex.end(), notIsAscii), _vertex.end());
	string _frag = ss1.str(); _frag.erase(remove_if(_frag.begin(), _frag.end(), notIsAscii), _frag.end());

	// Get Vertex And Fragment Shader Sources
	my_fragment_shader_source = _frag.c_str();
	my_vertex_shader_source = _vertex.c_str();

        //DEBUG - can remove
	cout &lt;&lt; &quot;vertex shader:&quot;&lt;&lt;endl&lt;&lt;my_vertex_shader_source&lt;&lt;endl;
	cout &lt;&lt; &quot;fragment shader:&quot;&lt;&lt;endl&lt;&lt;my_fragment_shader_source&lt;&lt;endl;

	GLvoid* my_vertex_shader;
	GLvoid* my_fragment_shader;

	// Create Shader And Program Objects
	my_program = glCreateProgramObjectARB();
	my_vertex_shader = glCreateShaderObjectARB(GL_VERTEX_SHADER_ARB);
	my_fragment_shader = glCreateShaderObjectARB(GL_FRAGMENT_SHADER_ARB);

	// Load Shader Sources
	glShaderSourceARB(my_vertex_shader, 1, &amp;my_vertex_shader_source, NULL);
	checkARBError(my_vertex_shader);
	glShaderSourceARB(my_fragment_shader, 1, &amp;my_fragment_shader_source, NULL);
	checkARBError(my_fragment_shader);

	// Compile The Shaders
	glCompileShaderARB(my_vertex_shader);
	checkARBError(my_vertex_shader);
	glCompileShaderARB(my_fragment_shader);
	checkARBError(my_fragment_shader);

	// Attach The Shader Objects To The Program Object
	glAttachObjectARB(my_program, my_vertex_shader);
	glAttachObjectARB(my_program, my_fragment_shader);
	checkARBError(my_program);

	// Link The Program Object
	glLinkProgramARB(my_program);
	checkARBError(my_program);

}
</pre>
<p>I based it on <a href="http://nehe.gamedev.net/article/glsl_an_introduction/25007/" target="_blank">this example</a> from NeHe.</p>
<p>It does periodical error checking so you can see if something is wrong, plus it will make sure the vertex shader and fragmetn shader are stripped of all non-ASCII characters.<br />
This way the compilation will not give you cryptic errors such as &#8220;ERROR: 0:1: &#8216;<&#8216; : syntax error syntax error&#8221;&#8230;</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F10%2F30%2Fa-glsl-shader-showing-the-normal-map-w-code%2F&amp;title=A%20GLSL%20shader%20showing%20the%20normal%20map%20%5Bw%2F%20code%5D" id="wpa2a_10"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/10/30/a-glsl-shader-showing-the-normal-map-w-code/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Android frame animation revisited [w/ code]</title>
		<link>http://www.morethantechnical.com/2011/10/17/android-frame-animation-revisited-w-code/</link>
		<comments>http://www.morethantechnical.com/2011/10/17/android-frame-animation-revisited-w-code/#comments</comments>
		<pubDate>Mon, 17 Oct 2011 15:06:54 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[Android]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[Mobile phones]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[frame]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=946</guid>
		<description><![CDATA[So, been working hard on my projects, and discovered some interesting things in Android possibilities for frame animation. Last time I was using an HTML approach, because of memory consumption issues with using ImageViews. However now my approach is using View.onDraw(Canvas) to draw BMPs straight off files, in an asynchronous way, and it seems to [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/10/android_will_allow2.png" rel="lightbox[946]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/10/android_will_allow2-300x279.png" alt="" title="android_will_allow" width="300" height="279" class="alignleft size-medium wp-image-954" /></a>So, been working hard on my projects, and discovered some interesting things in Android possibilities for frame animation. Last time I was using an <a href="http://www.morethantechnical.com/2011/03/01/the-woes-of-frame-animation-on-android-w-code/">HTML approach</a>, because of memory consumption issues with using ImageViews. However now my approach is using View.onDraw(Canvas) to draw BMPs straight off files, in an asynchronous way, and it seems to work pretty good.<br />
Let me tell you how I did it<br />
<span id="more-946"></span><br />
The general idea was explained in the preface, and the technicality is as follows. I plainly subclass View, and override onDraw(Canvas):</p>
<pre class="brush: plain; title: ; notranslate">
public class MyCanvasView extends View {
...
private Bitmap bmp;
private Lock bmpLock;
private Animator a;
private float scale = 1.0f;
private Rect clip;

@Override
protected void onDraw(Canvas canvas) {
   super.onDraw(canvas);
   ...
   clip = canvas.getClipBounds();
   w = clip.width();
   w2 = w/2.0f;
   h = clip.height();
   h2 = h/2.0f;

   bmpLock.lock();
   float left = scale*(w2 - (float)bmp.getWidth()/2.0f);
   float top = scale*(h2 - (float)bmp.getHeight()/2.0f);

   Bitmap _bmp = bmp;
   canvas.drawBitmap(_bmp, left, top, paint);
   bmpLock.unlock();
   ...
}
}
</pre>
<p>To drive the animation I privately subclass a Thread, that will push out new Bitmap objects (or at least write into the data of the private Bitmap object).</p>
<pre class="brush: plain; title: ; notranslate">
private class Animator extends Thread {
   private final MyCanvasView myCanvasView;
   private AssetManager assets;
   private int start = 0;
   private int end = 10;
   private boolean loop = false;

   public Animator(MyCanvasView myCanvasView)
   {
      this.myCanvasView = myCanvasView;
      assets = myCanvasView.getContext().getAssets();
   }

   @Override
   public void run() {
   super.run();

   try {
      do {
         for (int i = start; i &lt;= end; i++) {
            boolean bitmapLoaded;
            bitmapLoaded = tryLoadBitmap(&quot;anim&quot; + new DecimalFormat(&quot;0000&quot;).format(i) + &quot;.png&quot;);
            if(!bitmapLoaded) { break; }
         }
      } while(loop);
   } catch (InterruptedException e) {
      e.printStackTrace();
   }
   }

   private boolean tryLoadBitmap(String bmpFilename) throws InterruptedException {
      try {
         bmpLock.lock();
         bmp = BitmapFactory.decodeStream(assets.open(bmpFilename));
         bmpLock.unlock();
         if(bmp == null) {
            AlertDialog a = new AlertDialog.Builder(getContext()).create();
            a.setMessage(&quot;Cannot load image&quot;);
            a.show();
            return false;
         }
         myCanvasView.postInvalidate();
         sleep(25);
      } catch (IOException e) {
         e.printStackTrace();
      }
      return true;
   }
}
</pre>
<p>Notice the usage of the Lock bmpLock object to prevent racing conditions on the drawing and loading of new Bitmaps.<br />
Also, you should probably want a mechanism to determine <code>start</code>, <code>end</code> and <code>loop</code> parameters. In the complete source you can see what I have done to address that.</p>
<p>Finally, a way to fire an animation on MyCanvasView:</p>
<pre class="brush: plain; title: ; notranslate">
public void fireAnimation() {
   if(a != null &amp;&amp; a.isAlive()) {
      a.interrupt();
      a = null;
   }
   a = new Animator(this);
   a.start(); //TODO: reuse the object
}
</pre>
<p>This runs in excellent frame rates, and it&#8217;s not even fully optimized. So I guess the approach is correct for the Android environment. I did not, however, test this with many animators on the same layout.</p>
<p>Grab the complete source (including some stuff I didn&#8217;t discuss here like rotating and scaling the &#8220;Sprite&#8221;):<br />
<code></p>
<p>https://raw.github.com/royshil/HeadFollower/master/src/edu/mit/media/fluid/royshil/graphics/MyCanvasView.java</p>
<p></code></p>
<p>This is part of the <a href="https://github.com/royshil/HeadFollower">PoCoMo</a> project I have been working on in our lab.</p>
<p>Enjoy!<br />
Roy.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F10%2F17%2Fandroid-frame-animation-revisited-w-code%2F&amp;title=Android%20frame%20animation%20revisited%20%5Bw%2F%20code%5D" id="wpa2a_12"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/10/17/android-frame-animation-revisited-w-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Neat OpenCV smoothing trick when Kineacking (Kinect Hacking) [w/ code]</title>
		<link>http://www.morethantechnical.com/2011/03/05/neat-opencv-smoothing-trick-when-kineacking-kinect-hacking-w-code/</link>
		<comments>http://www.morethantechnical.com/2011/03/05/neat-opencv-smoothing-trick-when-kineacking-kinect-hacking-w-code/#comments</comments>
		<pubDate>Sat, 05 Mar 2011 20:57:26 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[3d]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[vision]]></category>
		<category><![CDATA[depth]]></category>
		<category><![CDATA[inpainting]]></category>
		<category><![CDATA[kinect]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=824</guid>
		<description><![CDATA[I found a nice little trick to ease the work with the very noisy depth image the Kinect is giving out. The image is filled with these &#8220;blank&#8221; values that basically note where the data is unreadable. The secret is to use inpainting to cover these areas and get a cleaner image. And as always, [...]]]></description>
			<content:encoded><![CDATA[<p>I found a nice little trick to ease the work with the very noisy depth image the Kinect is giving out. The image is filled with these &#8220;blank&#8221; values that basically note where the data is unreadable. The secret is to use inpainting to cover these areas and get a cleaner image. And as always, no need to dig deep &#8211; OpenCV has it all included.<br />
<span id="more-824"></span></p>
<p>Start from a simple Kinect frames feed from <a href="http://openkinect.org/wiki/C%2B%2BOpenCvExample">here</a>:</p>
<pre class="brush: plain; title: ; notranslate">

int main(int argc, char **argv) {
	bool die(false);

	Mat depthMat(Size(640,480),CV_16UC1);
	Mat depthf  (Size(640,480),CV_8UC1);
	Mat rgbMat(Size(640,480),CV_8UC3,Scalar(0));
	Mat ownMat(Size(640,480),CV_8UC3,Scalar(0));

        Freenect::Freenect freenect;
        MyFreenectDevice&amp; device = freenect.createDevice&lt;MyFreenectDevice&gt;(0);

	device.startVideo();
	device.startDepth();

    while (!die) {
    	device.getVideo(rgbMat);
    	device.getDepth(depthMat);
    	depthMat.convertTo(depthf, CV_8UC1, 255.0/2048.0);
        cv::imshow(&quot;depth&quot;,depthf);
		char k = cvWaitKey(5);
		if( k == 27 ){
			break;
		}
    }

   	device.stopVideo();
	device.stopDepth();
	return 0;
}
</pre>
<p>Now let&#8217;s stretch the signal a little bit and add the inpainting:</p>
<pre class="brush: plain; title: ; notranslate">
		//interpolation &amp; inpainting
		{
			Mat _tmp,_tmp1; //minimum observed value is ~440. so shift a bit
			Mat(depthMat - 400.0).convertTo(_tmp1,CV_64FC1);

			Point minLoc; double minval,maxval;
			minMaxLoc(_tmp1, &amp;minval, &amp;maxval, NULL, NULL);
			_tmp1.convertTo(depthf, CV_8UC1, 255.0/maxval);  //linear interpolation

                       //use a smaller version of the image
			Mat small_depthf; resize(depthf,small_depthf,Size(),0.2,0.2);
                        //inpaint only the &quot;unknown&quot; pixels
			cv::inpaint(small_depthf,(small_depthf == 255),_tmp1,5.0,INPAINT_TELEA);

			resize(_tmp1, _tmp, depthf.size());
			_tmp.copyTo(depthf, (depthf == 255));  //add the original signal back over the inpaint
		}
</pre>
<p>Note that I&#8217;m using a small copy of the image, because inpainting is a heavy computation, and it works best on low frequencies. I copy back the original signal over the up-sized inpainted one to retain high frequencies.</p>
<p>It works pretty well!<br />
<object width="425" height="344"><param name="movie" value="http://www.youtube.com/v/Jm8yflH5BDs?hl=en&#038;fs=1"></param><param name="allowFullScreen" value="true"></param><param name="allowscriptaccess" value="always"></param><embed src="http://www.youtube.com/v/Jm8yflH5BDs?hl=en&#038;fs=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="344"></embed></object></p>
<p>Enjoy<br />
Roy.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F03%2F05%2Fneat-opencv-smoothing-trick-when-kineacking-kinect-hacking-w-code%2F&amp;title=Neat%20OpenCV%20smoothing%20trick%20when%20Kineacking%20%28Kinect%20Hacking%29%20%5Bw%2F%20code%5D" id="wpa2a_14"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/03/05/neat-opencv-smoothing-trick-when-kineacking-kinect-hacking-w-code/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>The woes of Frame Animation on Android [w/ code]</title>
		<link>http://www.morethantechnical.com/2011/03/01/the-woes-of-frame-animation-on-android-w-code/</link>
		<comments>http://www.morethantechnical.com/2011/03/01/the-woes-of-frame-animation-on-android-w-code/#comments</comments>
		<pubDate>Tue, 01 Mar 2011 05:48:24 +0000</pubDate>
		<dc:creator>Roy</dc:creator>
				<category><![CDATA[graphics]]></category>
		<category><![CDATA[Java]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[android]]></category>
		<category><![CDATA[animation]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[imagemagick]]></category>
		<category><![CDATA[java]]></category>

		<guid isPermaLink="false">http://www.morethantechnical.com/?p=822</guid>
		<description><![CDATA[My adventures of getting frame animation on the Android 2.1 continue, and take a turn for the worse. Will I come up victorious in the end? Not sure&#8230; Using Android&#8217;s Frame Animation API The first attempt I took at frame animation was using Android&#8217;s own AnimationDrawable. I thought it would give me the best solution, [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.morethantechnical.com/wp-content/uploads/2011/03/android_frame.png" rel="lightbox[822]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/03/android_frame-269x300.png" alt="" title="android_frame" width="269" height="300" class="alignleft size-medium wp-image-831" /></a>My adventures of getting frame animation on the Android 2.1 continue, and take a turn for the worse. Will I come up victorious in the end? Not sure&#8230;</p>
<p><span id="more-822"></span></p>
<h2>Using Android&#8217;s Frame Animation API</h2>
<p>The first attempt I took at frame animation was using Android&#8217;s own <a href="http://developer.android.com/guide/topics/graphics/2d-graphics.html#frame-animation">AnimationDrawable</a>. I thought it would give me the best solution, as it&#8217;s the closest to the native OS and probably optimized. I was wrong.<br />
This API is highly suspect to OutOfMemory exceptions, either when loading an animation of more than ~50 frames, an when loading more than one animation. On top of that, it is not doing a great job at displaying the frames, and produces a lot of jitter.</p>
<p>So using it is very very simple, and I wrote about it in a <a href="http://www.morethantechnical.com/2011/02/07/some-things-i-learned-about-androids-frame-animation/">previous post</a>, when I was still trying to make it work.</p>
<p>Basically, all you need is an ImageView to display your animation. Prepare some <a href="http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html">AnimationDrawable</a> in XML. Then you can either <a href="http://www.morethantechnical.com/2011/02/07/some-things-i-learned-about-androids-frame-animation/">pre-load an animation</a>, or just fire an animation regularly, which is only <a href="http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html">setting the Drawable</a> for the ImageView.</p>
<p>If you fire the animation more than once, remember to <a href="http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html#setVisible(boolean, boolean)">reset</a> it.</p>
<p>This is by far the simplest way to go, and best if you have a simple animation. But it dies very quickly of memory issues if you push it too hard.</p>
<h2>Using HTML and animated GIFs</h2>
<p>This seemed like a classical solution for frame animation. The browser should have absolutely no problems playing it &#8211; so I thought. Turns out Android 2.1&#8242;s web browser doesn&#8217;t play animated GIFs! So when I was working on my development phone, a 2.2er, there was no problem, but when I switched to my deployment phone, a 2.1er , the screen just goes black.<br />
If you&#8217;re on 2.2 &#8211; this a very nice way to frame animate. It&#8217;s clean and works at high frame rates.</p>
<p>First you would need to obtain animated GIFs that are compatible with Android&#8217;s web browser. I did that using <a href="http://www.imagemagick.org/Usage/anim_basics/">ImageMagick&#8217;s (IM) animation toolbox</a>. </p>
<pre class="brush: plain; title: ; notranslate">
convert myanim_split_*.png myanim.gif
</pre>
<p>But&#8230; there are some details to attend to. First, you probably would like to have control over looping the animation, that can be done using the <code>-loop</code> parameter of <code>convert</code>, setting it to 1 will play the animation once, 0 will loop forever.<br />
How about transparent background? this is very important for character animation, that usually live in a &#8220;world&#8221; and should not occlude the background. Well, if your animation&#8217;s PNGs have the background transparet, that would reflect in the animated GIF. But, just creating a GIF out of your PNGs will give you something like this:<br />
<a href="http://www.morethantechnical.com/wp-content/uploads/2011/02/anim.gif" rel="lightbox[822]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/02/anim.gif" alt="" title="anim" width="320" height="240" class="aligncenter size-full wp-image-825" /></a></p>
<p>The background is not clearing frame-to-frame. So add in the <code>-set dispose background</code> (or &#8220;dispose previous&#8221; to the IM line:</p>
<pre class="brush: plain; title: ; notranslate">
convert myanim_split_*.png -set dispose background myanim.gif
</pre>
<p>Now it looks better, and also has a transparent background:<br />
<a href="http://www.morethantechnical.com/wp-content/uploads/2011/02/anim1.gif" rel="lightbox[822]"><img src="http://www.morethantechnical.com/wp-content/uploads/2011/02/anim1.gif" alt="" title="anim" width="320" height="240" class="aligncenter size-full wp-image-826" /></a></p>
<p>There&#8217;s still the issue of showing it up as part of the layout, and that will be done with WebView. The tricky part is controlling when the animation will fire. There are several ways to go about it, such as loading a single HTML file and using <code>webview.loadUrl</code> with a &#8220;javascript:&#8230;&#8221; URL to replace the image, or using a simpler method of <code>webview.loadData</code> with HTML code that just displays the image with <code>&lt;img src=".."&gt;</code>. There is no &#8220;right way&#8221; as this is the &#8220;hack way&#8221; anyway.</p>
<pre class="brush: plain; title: ; notranslate">
WebView wb = (WebView) findViewById(R.id.webview);
wb.loadDataWithBaseURL(
		&quot;fake://lala&quot;,
		&quot;&lt;div style=\&quot;text-align: center;\&quot;&gt;&lt;IMG id=\&quot;myanim\&quot; SRC=\&quot;file:///android_asset/myanim.gif\&quot; style=\&quot;height: 100%\&quot; /&gt;&lt;/div&gt;&quot;,
		&quot;text/html&quot;,
		&quot;UTF-8&quot;,
		&quot;fake://lala&quot;);
</pre>
<p>Notice that the GIF file must reside in the &#8220;assets&#8221; directory of the android project, and the &#8220;file:///android_asset/&#8221; URL goes right to there. You may as well skip the whole HTML thing and just have WebView loadURL the GIF file right away.</p>
<p>Now this will work on Android 2.2 and up, but will fail for Android 2.1 as the web browser doesn&#8217;t implement animated GIFs yet.</p>
<h2>Using MediaPlayer and animated GIFs</h2>
<p>I saw somewhere that even though the WebView in 2.1 cannot play GIFs, the MediaPlayer sure can, so it&#8217;s worth mentioning that.</p>
<p>So I set up a surface in the layout</p>
<pre class="brush: plain; title: ; notranslate">
&lt;SurfaceView android:id=&quot;@+id/mysurfaceview&quot;
	android:layout_width=&quot;fill_parent&quot;
	android:layout_height=&quot;0dip&quot;
	android:layout_weight=&quot;1&quot;
	/&gt;
</pre>
<p>Got the holder in code, and instantiated a MediaPlayer</p>
<pre class="brush: plain; title: ; notranslate">
mCharPreview = (SurfaceView) findViewById(R.id.mysurfaceview);
holder = mCharPreview.getHolder();
holder.addCallback(this);
extras = getIntent().getExtras();

mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDisplay(holder);
mMediaPlayer.setOnCompletionListener(this);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnBufferingUpdateListener(this);
mMediaPlayer.setOnVideoSizeChangedListener(this);
mMediaPlayer.setAudioStreamType(AudioManager.);
</pre>
<p>And then listen on surfaceCreated to prepare the player</p>
<pre class="brush: plain; title: ; notranslate">
public void surfaceCreated(SurfaceHolder holder) {
        try {
            AssetFileDescriptor openFd = getAssets().openFd(&quot;myanim.gif&quot;);
		mMediaPlayer.setDataSource(openFd.getFileDescriptor());
            mMediaPlayer.prepare();
	} catch (Exception e) {
		e.printStackTrace();
		(new AlertDialog.Builder(this)).setTitle(&quot;Exception&quot;).setMessage(e.getClass().getName() + &quot;:&quot; + e.getLocalizedMessage()).create().show();
	}
}
</pre>
<p>Then listen on prepared to start the animation</p>
<pre class="brush: plain; title: ; notranslate">
public void onPrepared(MediaPlayer mediaplayer) {
        mIsVideoReadyToBePlayed = true;
        if (mIsVideoReadyToBePlayed) {
             holder.setFixedSize(200, 300);
             mMediaPlayer.start();
        }
}
</pre>
<p>But &#8211; this code failed for me in the <code>mMediaPlayer.prepare()</code> with an exception like <code>"Prepare failed.: status=0xFFFFFFF"</code>. I&#8217;m guessing that the player fails because the format is not recognized.</p>
<h2>Using HTML and Javascript</h2>
<p>So, after being exhausted with having some engine play the animation, I decided to go back to using WebView with Javascript code to flip the images one after the other.</p>
<p>Well this was pretty straight forward, I created a small HTML code:</p>
<pre class="brush: plain; title: ; notranslate">
&lt;html&gt;
 &lt;script&gt;
 //---------------------------------------------------------------
//just a function to pad numbers with 0s, good for animation frames in sequential files...
 function FormatNumberLength(num, length) {
    var r = &quot;&quot; + num;
    while (r.length &lt; length) {
        r = &quot;0&quot; + r;
    }
    return r;
}
//---------------------------------------------------------------

  var state=0;
  var myinterval = -1; //JS interval handler

//---------------------------------------------------------------
//parse querystring - that's where I get the image to show, and other parameters
  var qs = (function(a) {
    if (a == &quot;&quot;) return {};
    var b = {};
    for (var i = 0; i &lt; a.length; ++i)
    {
        var p=a[i].split('=');
        b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, &quot; &quot;));
    }
    return b;
  })(window.location.search.substr(1).split('&amp;'));
//---------------------------------------------------------------

  var firstFrame = parseInt(qs[&quot;first&quot;]);   //the index of the first frame
  var lastFrame = parseInt(qs[&quot;last&quot;]);    //the index of the last frame

//---------------------------------------------------------------
  // intializes animation timer
  function ini() {
  	if(firstFrame &gt;= 0) { //animation
    	setTimeout(&quot;myinterval = setInterval(\&quot;periodic()\&quot;,100);&quot;,100);
    } else {				//static
    	document.getElementById(&quot;myimg&quot;).src=&quot;file:///android_asset/&quot;+ qs[&quot;anim_file&quot;] +&quot;.png&quot;;
    }
  }
//---------------------------------------------------------------

  // called regularly to perform animation
  function periodic() {
    state+=2;  //jump by 2 frames? can change this to 1 if you like...
    animState = firstFrame + state;

    if (animState &lt;= lastFrame) {
		document.getElementById(&quot;myimg&quot;).src=&quot;file:///android_asset/&quot;+ qs[&quot;anim_file&quot;] + FormatNumberLength(animState,4) +&quot;.png&quot;;
    }
    else {
    	if(qs[&quot;loop&quot;] == &quot;false&quot;)  //'loop' will say if we keep playing the animation.. duh
    		clearInterval(myinterval);
    	else
    		state = 0;
    }
  }

 &lt;/script&gt;
 &lt;style&gt;
 #wrapper {
     text-align: center;
     background-color: black; /* make sure to use this, since sometimes there are ghosts */
 }
 #im {
     background-color: black;
 }
 &lt;/style&gt;
 &lt;body onLoad=&quot;ini()&quot;&gt;
  &lt;div id=&quot;wrapper&quot;&gt;
     &lt;img id=&quot;myimg&quot; src=&quot;&quot;/&gt; &lt;!--   this is where the image goes --&gt;
  &lt;/div&gt;
 &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Put this file, as usual, in the &#8220;assets&#8221; directory where it can be found easily with the <code>"file:///android_assets/..."</code> URL.</p>
<p>So, this HTML is loaded into the WebView with some parameters on the URL that will tell it what to show, like so:</p>
<pre class="brush: plain; title: ; notranslate">
       //This class holds all we need for an animation: filename, number of frames, etc.
	private class MyAnim {
		String filename;
		int start;
		int end;
		boolean loop;
		public MyAnim(String filename, int start, int end) {
			super();
			this.filename = filename;
			this.start = start;
			this.end = end;
			this.loop = false;
		}
		public MyAnim(String filename, int start, int end, boolean loop) {
			super();
			this.filename = filename;
			this.start = start;
			this.end = end;
			this.loop = loop;
		}
	}

        //this function will &quot;fire&quot; an animation, essentially load the HTML code with the proper parameters
	private void fireAnimation(final MyAnim myAnim, final boolean shouldTurn) {
		findViewById(R.id.webview).post(new Runnable() {
			@Override
			public void run() {
				long now = (new Date()).getTime();
				if((now - anim_start_ts) &lt; 2000) return; //let other animations finish man! geez...

				WebView wb = (WebView) findViewById(R.id.webview);

				//supply the &quot;base&quot; filename, the first frame number, last frame and should the animation repeat
				wb.loadUrl(&quot;file:///android_asset/animate.html?anim_file=&quot;+myAnim.filename+&quot;&amp;first=&quot;+myAnim.start+&quot;&amp;last=&quot;+myAnim.end+&quot;&amp;loop=&quot;+myAnim.loop);
				wb.invalidate();

				anim_start_ts = now;
			}
		});
	}
</pre>
<p>The filenames should be sequential, like: &#8220;myanim0001.jpg&#8221;, &#8220;myanim0002.jpg&#8221;, &#8230;.<br />
And then an animation may be from the file &#8220;mayanim0023.jpg&#8221; to &#8220;myanim0046.jpg&#8221;. The parameters for the HTML code will be then: <code>anim_file="myanim"&#038;first=23&#038;last=46</code>.</p>
<p>But! We are not done.<br />
Because stupid Android 2.1 does not clear the first image that loads into the <code>&lt;img ... &gt;</code>!<br />
So you get these weird &#8220;ghosting&#8221; effects, where the new images of the animation are shown superimposed on the first image&#8230;<br />
I couldn&#8217;t get past this, so I found another way of doing it&#8230;.</p>
<h2>Using HTML, JS and innerHTML</h2>
<p>This is what I ended up using.<br />
Basically everything stays the same, except for the fact that now we are not leaving the <code>&lt;img ... &gt;</code> in there to ghost stuff up, we&#8217;re completely replacing it with new HTML code using innerHTML.</p>
<p>The change is slight, in the JS I used:</p>
<pre class="brush: plain; title: ; notranslate">
    	document.getElementById(&quot;wrapper&quot;).innerHTML=
	    	&quot;&lt;div style=\&quot;-webkit-transform: scaleX(&quot;  +  ((qs[&quot;flip&quot;]==&quot;0&quot;)?&quot;-1&quot;:&quot;1&quot;)  +  &quot;);\&quot;&gt;&quot;+
	    	&quot;&lt;img id=\&quot;im\&quot; style=\&quot;height:100%\&quot; src=\&quot;file:///android_asset/&quot;+ qs[&quot;anim_file&quot;]+&quot;\&quot; /&gt;&quot;+
	    	&quot;&lt;/div&gt;&quot;;
</pre>
<p>Note that now I also introduced a new parameter: &#8220;flip&#8221;, that uses <code>-webkit-transform</code> to flip the displayed image.</p>
<p>Phew, that was a battle. I won. And now we learned a few things about Android and options for frame animation.<br />
Some other options to explore: flipping OpenGLES textures, encoding animations to mp4s?</p>
<p>Please share your experience with Android frame animation!</p>
<p>Roy.</p>
<p>Portions of this page are modifications based on work created and <a href="http://code.google.com/policies.html">shared by Google</a> and used according to terms described in the <a href="http://creativecommons.org/licenses/by/3.0/">Creative Commons 3.0 Attribution License</a>.</p>
<p><a class="a2a_dd a2a_target addtoany_share_save" href="http://www.addtoany.com/share_save#url=http%3A%2F%2Fwww.morethantechnical.com%2F2011%2F03%2F01%2Fthe-woes-of-frame-animation-on-android-w-code%2F&amp;title=The%20woes%20of%20Frame%20Animation%20on%20Android%20%5Bw%2F%20code%5D" id="wpa2a_16"><img src="http://www.morethantechnical.com/wp-content/plugins/add-to-any/share_save_171_16.png" width="171" height="16" alt="Share"/></a></p>]]></content:encoded>
			<wfw:commentRss>http://www.morethantechnical.com/2011/03/01/the-woes-of-frame-animation-on-android-w-code/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

