Thursday, January 29, 2009

Anaglyphs and 3D vision

Oh a post about vision systems (about time!)

So you can write alot of code to try and interpret the 3D space in images or you can cheat and use the same technique that the brian uses (well it probably does not use pointers but thats another conversation)

So if you have two cameras you can position them side by side like eyes, and using a bit of DirectX coding take some pictures at the same time:

left

right

In the pictures above you can see that the images are slightly offset from each other (the wall on the left is not visible in the right picture), and from this you can generate Anaglyph image:
Anaglyph

Now if you put your 3D spec's on (the kind that came with Shrek 3D DVD) you can see it in 3D!

The code? something like this does the trick (cue screams of fear! its unsafe code! it's got pointers and stuff! hide behind the sofa!
unsafe public Bitmap MakeAnaglyph()
  {
   Bitmap result = (Bitmap)_right.Clone();

   FastBitmap fbitRight = new FastBitmap(result, ImageLockMode.ReadWrite);
   FastBitmap fbitLeft = new FastBitmap(_left);

   FastBitmap.PixelData* pPixelRight;
   FastBitmap.PixelData* pPixelLeft;

   for (int y = 0; y < _right.Height; y++)
   {
    for (int x = 0; x < _right.Width; x++)
    {
     pPixelRight = fbitRight[x, y];
     pPixelLeft = fbitLeft[x, y];

     pPixelRight->red = pPixelLeft->red;
     pPixelRight->green = (byte)(pPixelRight->green * .82);
     pPixelRight->blue = (byte)(pPixelRight->blue * .95);
    }
   }

   fbitRight.Dispose();
   fbitLeft.Dispose();

   return result;
  }

This code uses my FastBitmap class, which justs makes working with the raw data a bit more obvious:
unsafe class FastBitmap: IDisposable
 {
  Bitmap _source;
  Rectangle _bounds;
  BitmapData _lockedBitmap;
  byte* _pBase;
  int _stride;

  [StructLayout(LayoutKind.Sequential)]
  public struct PixelData
  {
   public byte blue;
   public byte green;
   public byte red;
  }

  public FastBitmap(Bitmap source): this(source, ImageLockMode.ReadOnly)
  {
  }

  public FastBitmap(Bitmap source, ImageLockMode mode)
  {
   _source = source;
   _bounds = Bounds;
   _lockedBitmap = _source.LockBits(_bounds, mode, source.PixelFormat);
   _pBase = (byte*)(void*)_lockedBitmap.Scan0;
   _stride = _lockedBitmap.Stride;
  }
  public PixelData* this[int x, int y]
  {
   get
   {
    // Format32bppArgb - Specifies that the format is 32 bits per pixel; 
    // 8 bits each are used for the alpha, red, green, and blue components
    const int bytesPerPixel = 4; 

    PixelData* result = (PixelData*)(_pBase + (y * _stride) + (x * bytesPerPixel));

    return result;
   }
  }

  public Rectangle Bounds
  {
   get
   {
    GraphicsUnit unit = GraphicsUnit.Pixel;
    RectangleF bounds = _source.GetBounds(ref unit);

    Rectangle result = SizeToRectangle(bounds.Location, bounds.Size.ToSize());

    return result;
   }
  }


  private Rectangle SizeToRectangle(Size size)
  {
   return SizeToRectangle(new Point(0, 0), size);
  }

  private Rectangle SizeToRectangle(Point point, Size size)
  {
   return new Rectangle(point, size);
  }

  private Rectangle SizeToRectangle(PointF point, Size size)
  {
   return new Rectangle(new Point((int)point.X, (int)point.Y), size);
  }

  #region IDisposable Members

  public void Dispose()
  {
   if (_lockedBitmap != null)
   {
    _source.UnlockBits(_lockedBitmap);
    _lockedBitmap = null;
   }
  }

  #endregion
 }

How does this get you nearer to 3D vision? hint: red-blue differencing of the result...

¡ ¡uΜop ǝpısdn ʞɔnʇs uǝǝɹɔs sdo



¡¡¡uΜop ǝpısdn ʞɔnʇs uǝǝɹɔs sdo




[CTRL-D]

fun with typography

Periodic Table of Visualization Methods

An interactive interface covering many techniques for visualization

source: visual-literacy.org

Wednesday, January 28, 2009

Oslo, DSL and maps

oh, there could be some fun to be had here...

Oslo || DSL || OpenStreetMap = fun

A Lap around "Oslo"
"Oslo": Building Textual DSLs

must resist... finish map first... argh!

Moonlight, Silverlight and OpenStreetMap

One of the nice things about creating the map in Silverlight has been the possibilty of using a Moonlight client to reach even more users..

however I seem to be causing problems in moonlight with my OpenStreetMap in Silverlight..

Bad me! I suspect this is because I am really pushing the Silverlight threading model - the application is very UI intensive, which is something that (ironically) Silverlight has problems with (You can't multi-thread UI calls, so everything bottlenecks waiting for Dispatch).

I will try and see if I can help the Moonlight guys with the fixin'

I've been a bit quite on the map front - mainly due to re-engineering the Quadstore to handle the whole planet - this is still ongoing (I'm trying to keep conversion time from OSM dataset to Quadstore to under an hour, and at the same time not use SQL Server)

I have updated the demo to improve a few things:
  • Points of Interest now supported (though theres not mainly in my test data set, my fault not OSM's - I filtered them out, next data upload will fix this) You can see them as blue/red triangles. Hopefully I should be able to start demonstrating the power of the dynamic approach by allowing users to select what POIs to show on the fly.
  • Where's FE? this is really me just playing - from my post on mobile location finding I've added the capability to the cobalt server to track users. My windows smartphnone mobile phone tells the server where it is and this is shown as a little icon - in the future a user can download this app and put their own details in. They can then show this on their own map, and if the choose allow other (selected users) to see their location. You will also be able to tell the system how accurate you want the position to be (so the icon can be placed anywhere within, 100, 10, 1, exact square meters.
  • Road smoothing - I've improved this algorithm to speed this up, mainly by reducing it from O(n2) to O(n) by using a "smarter" approach.
  • Performance - I did a lot of profiling combined with improving the road smoothing alg, has made the map faster, however I'm still unhappy with the 30sec draw time - faster computer do this in about 12-15 seconds. This is too slow, so performance is still on the agenda. I had some good feedback from emj on OpenStreetMap on this - thanks!
The next release of the map should support the full world and complete pan/zoom control..

Tuesday, January 20, 2009

Obama: Start?

A moving event, and great speech - hopefully there will be substance to follow:


(picture created using http://obamiconme.pastemagazine.com/)

 And to misuse a quote "It's the economy, climate, energy security, healthcare, etc, stupid"

Friday, January 16, 2009

Silverlight tag cloud v1.4

A bug fix to the Silverlight code, in rare cases it colours very frequently co-occurring tags so they are hard to see.

I've updated the Silverlight XAP file and pointed the javascript to use this version - so anyone using 1.3 will not have to do anything to get this fix.


I've also created a super-sized version as a holding page for my www site, it's interesting to see how it performs given more space.

Wednesday, January 14, 2009

Insert coin to continue...

Argh! don't start playing this game:

(sounds starts automagically)

The Fear, a catchy song...



"But it doesn't matter cause I’m packing plastic
and that's what makes my life so f*[king fantastic

And I am a weapon of massive consumption
and its not my fault it's how I'm programed to function"

;-)

Little Boots and Tenori-on

Little Boots has an interesting sound, but also a very interesting device, a sequencer that has an unusual interface - in effect expressing the time-tone space in a physical 2d form:


and REALLY see her using it:


This look like a nice interface for a multi-touch device...

check out more of little boots music

and more about the Tenori-on:

Thursday, January 8, 2009

Unit testing and Silverlight

Interesting post on NUnit & the Silverlight unit test framework

Though I'm not sure what the utility of running the test within Silverlight is (they are dev tests after all), maybe useful for running scripted user tests?





more on testing in Silverlight...

Wednesday, January 7, 2009

Getting mobile location on Windows Mobile 6

As part of my ongoing mapping project I wanted to be able to update my server with my location - the first step was to use the GPS built into my Windows Mobile 6.

I used the GPS Intermediate Driver to do this, and the code provided by the Windows Mobile 6 SDK.

The simplest code that can be written references the sample library provided by the SDK. My sub-80 line program to do this looks like this:

using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using Microsoft.WindowsMobile.Samples.Location;

namespace MobileLocate
{
 public partial class FormMain : Form
 {
  Gps gps = new Gps();
  GpsDeviceState device = null;
  GpsPosition position = null;

  public FormMain()
  {
   InitializeComponent();

   // updates from GPS need to be delgate to the UI thread
   EventHandler uiUpdatesOnApplicationThread = new EventHandler(UpdateUI);

   // handle device state updates
   gps.DeviceStateChanged += new DeviceStateChangedEventHandler(delegate(object sender, DeviceStateChangedEventArgs args)
   {
    device = args.DeviceState;

    Invoke(uiUpdatesOnApplicationThread);
   });

   // handle location updates
   gps.LocationChanged += new LocationChangedEventHandler(delegate(object sender, LocationChangedEventArgs args)
   {
    position = args.Position;

    Invoke(uiUpdatesOnApplicationThread);
   });

   gps.Open();
  }

  void UpdateUI(object sender, System.EventArgs args)
  {
   if (device != null)
    textBoxDev.Text = device.FriendlyName + " " + device.ServiceState + ", " + device.DeviceState;

   if (position != null)
   {
    if (position.LatitudeValid && position.LongitudeValid)
     textBoxLocation.Text = String.Format("{0}, {1}", position.Latitude, position.Longitude);

    if (position.SatellitesInSolutionValid &&
      position.SatellitesInViewValid &&
      position.SatelliteCountValid)
    {
     textBoxSats.Text = "Satellite Count:\n   " + position.GetSatellitesInSolution().Length + "/" +
       position.GetSatellitesInView().Length + " (" +
       position.SatelliteCount + ")\n";
    }
   }
  }

  private void FormMain_Closed(object sender, EventArgs e)
  {
   // ensures application closes cleanly
   if (gps.Opened)
    gps.Close();
  }
 }
}

I ran this just now, and stuck the co-ordinates into a map - and it works a treat!

I plan to extend this code to allow it to report into a central server (with a username/password) and then be able to show this on the map. This will form one of the overlays (more later on this) that can be incorporated onto a map - this means you could chose to have the location of a set of users appear on a map (they will have to be permissions on this, and maybe a "how precise" feature to mask exact location)

From the mobile viewpoint, it should be easy enough to use the vector maps to show a local map on the mobile phone as well. For the moment I may just add the ability for the system to tell you where you are (for example postcode in the UK using http://www.freethepostcode.org/ data), or just the nearest city or pub! ;-)

Tuesday, January 6, 2009

Fibonacci and Big-Oh reduction

I was asked to write some C# to implement a Fibonacci sequence, which falls into two parts: 1) generate a single number in the sequence, 2) generating the whole sequence.

Note that most examples of this sequence generator have a nasty bug in them. Most examples use the int data type, whilst this code uses the long data type, otherwise this function overflows around n=47.

The naive way to implement this is recursively:
  /// <summary>
  /// slow version of fib calc for testing - warning
  /// runs in O(1.618..n) 
  /// </summary>
  internal long Fibonacci(int n)
  {
   if (n < 2)
    return n;
   else
    return Fibonacci(n - 1) + Fibonacci(n - 2);
  }

And a more optimal approach is:
  /// <summary>
  /// returns the Fibonacci number for N
  /// </summary>
  public long Fibonacci(int n)
  {
   // returns N where n < 2, for higher values of N
   // avoids recursive solution by keeping track
   // of previous results

   long fn = 0;

   if (n < 0) // offset must be positive
    throw new NotSupportedException("Fibonacci sequence offset must be positive");
   else if (n < 2) // returns N where N < 2
    fn = n;
   else // use caching technique for higher values of N
   {
    long fnMinusTwo = 0;
    long fnMinusOne = 1;

    for (long ni = 2; ni <= n; ni++)
    {
     // effectively: fn = Fibonacci(n - 1) + Fibonacci(n - 2)
     fn = fnMinusOne + fnMinusTwo;

     fnMinusTwo = fnMinusOne;
     fnMinusOne = fn;
    }
   }

   return fn;
  }
The latter approach is much more efficient O(n) vs O(1.618..n). However its not as simple as the former. Another approach is to take the former solution and use a local cache:
  /// <summary>
  /// caching version of fib calc
  /// </summary>
  Dictionary<int, long> fibCache = new Dictionary<int, long>();
  internal long Fibonacci(int n)
  {
   long fn = 0;

   // use value from cache if already calculated
   if (fibCache.ContainsKey(n))
    return fibCache[n];

   // not cached, need to work it out
   if (n < 2)
    fn = n;
   else
    fn = Fibonacci(n - 1) + Fibonacci(n - 2);

   // add to cache
   fibCache.Add(n, fn);

   return fn;
  }
This gives us an O(n) runtime with a reasonably simple implementation. This is of course the classic trade-off of time vs. space - we have increased space used (the dictionary) to decrease time.

Finally we want to generate the whole sequence, which we can do in a lazy evaluation way using the yield keyword:
  /// <summary>
  /// returns the first N items in the Fibonacci sequence
  /// </summary>
  public static IEnumerable<long> FibonacciSequence(int n)
  {
   for (int fn = 0; fn < n; fn++)
    yield return Fibonacci(fn);
  }

International Blogging: Hello, world!

I was looking at the stats for this blog and was reminded again about the international nature of the Internet and how distances have shrunk.

Here is a partial snap-shot of some visitors for today:

 Asia/Pacific Region, 
 United States, West Palm Beach, Florida
 Australia, Sydney, New South Wales
 Hong Kong, Central District
 Unknown, 
 Germany, Berlin
 Poland, Radom
 Netherlands, Delft, Zuid-Holland
 India, Bombay, Maharashtra
 Australia, Sydney, New South Wales
 Malaysia, Penang, Pulau Pinang
 Asia/Pacific Region, 
 Sweden, Gteborg, Vastra Gotaland
 Russian Federation, Moscow, Moscow City
 Romania, Brasov
 Norway, Trondheim, Sor-Trondelag
 United States, Salt Lake City, Utah
 Japan, Suwa, Nagano
 Australia, Hastings, Victoria
 Vietnam, Hanoi, Dac Lac
 India, Bangalore, Karnataka
 Unknown, 
 Hong Kong, Kowloon
 India, Bombay, Maharashtra
 Korea, Republic of, 
 Malta, Attard
 United Kingdom, Salisbury, Wiltshire
 Canada, Brampton, Ontario
 United States, Atlanta, Georgia
 Canada, Brampton, Ontario
 Cote D'Ivoire, Abidjan
 United States, Las Vegas, Nevada
 Vietnam, Hanoi, Dac Lac
 Ireland, Dublin
 United Kingdom, 
 United States, Austin, Texas
 Japan, Tokyo
 Mexico, Chihuahua
 Canada, Toronto, Ontario
 Austria, Vienna, Wien
 Germany, Recklinghausen, Nordrhein-Westfa...
 Canada, Edmonton, Alberta
 Sweden, Blsta, Uppsala Lan
 United States, Chicago, Illinois
 United Kingdom, London, London, City of
 Austria, Vienna, Wien
 Netherlands, Den Haag, Zuid-Holland
 Sweden, Karlstad, Varmlands Lan
 Japan, Tokyo
 United States, Waban, Massachusetts
 Austria, 
 Portugal, Lisbon, Lisboa
 United States, Jonesboro, Georgia
 Malta, Naxxar
 Canada, Toronto, Ontario


so: Hello, world!