CLICK HERE FOR BLOGGER TEMPLATES AND MYSPACE LAYOUTS »

Saturday, 24 March 2012

Face Recognition Part 1: Detecting skin colour

Introduction

Face recognition is a difficult computer vision problem that needs to be tackled in several steps. The first major issue is detecting where faces are within the picture presented to the software and the very first step of this is to detect areas of skin colour within the picture.

Creating a skin model

There are a large range of skin colours that can be present within a picture and lighting conditions can make a big difference to identifying them. To be able to identify all different skin colours we need to generate a skin model that ignores the luminance of the colour.

To do this we produce an image with a large number of patches of different skin colours. We then use the following algorithm to build a basic colour map for skin colour:

Create a black image 400x400 pixels
For each pixel in the skin colour image
{
Convert the colour of the pixel to YCbCr (http://en.wikipedia.org/wiki/YCbCr)
Draw a white pixel on the black image at (Cb/256 * 400, Cr/256 * 400)
}

From a skin colour image like this:
The algorithm produces a basic colour map like this:


To remove noise from the colour map a binary erosion is applied (see the erode function in this post on Haishi's blog http://haishibai.blogspot.co.uk/2009/09/image-processing-find-binary-image.html) which produces the following skin model (Shown against the full YCbCr model and used as a mask to clearly show the colours identified as skin colour):

Skin Model after binary erosion

YCbCr colour space with Y=1

YCbCr colour space with Y=0

Using the skin model as a mask for the YCbCr colour space with Y=1

Using the skin model as a mask for the YCbCr colour space with Y=0

As you can see when we ignore the luminance (Y) the skin colour model is quite small but allows us to identify a wide range of different skin colours no matter how light or dark they are.

Now that we have a skin model bitmap we can project the colour of any pixel from a picture into the CbCr space that the model covers and test for a white pixel being present. If a white pixel is present then we have identified a skin colour pixel.

C# Code for the skin model:

using System;
using System.Drawing;

namespace EigenFaces
{
public class SkinModel
{
private Bitmap skinMap;
private Bitmap skinColourSpace;

public SkinModel()
{
this.skinColourSpace = new Bitmap(400, 400);

using(Graphics g = Graphics.FromImage(this.skinColourSpace))
{
g.FillRectangle(
Brushes.Black,
new Rectangle(
0,
0,
this.skinColourSpace.Width,
this.skinColourSpace.Height));
}

for (int x = 0; x < this.skinMap.Width; x++ )
{
for (int y = 0; y < this.skinMap.Height; y++)
{
Color pixel = this.skinMap.GetPixel(x, y);
double Cb = this.GetCb(pixel);
double Cr = this.GetCr(pixel);

int colourSpaceX = (int)((Cb/256) * 400);
int colourSpaceY = (int)((Cr/256) * 400);
this.skinColourSpace.SetPixel(
colourSpaceX,
colourSpaceY,
Color.White);
}
}

this.skinColourSpace = Erode(
this.skinColourSpace,
new bool[3, 3]
{
{ false, true, false },
{ true, true, true },
{ false, true, false }
},
3,
3);
}

private static bool ColoursEqual(Color c1, Color c2)
{
return ((c1.A == c2.A) &&
(c1.R == c2.R) &&
(c1.G == c2.G) &&
(c1.B == c2.B));
}

private static Bitmap Erode(
Bitmap normalisedImage,
bool[,] structure,
int structureWidth,
int structureHeight)
{
Bitmap erodedImage = new Bitmap(
normalisedImage.Width,
normalisedImage.Height);

for (int i = 0; i < erodedImage.Width; i++)
{
for (int j = 0; j < erodedImage.Height; j++)
{
bool keep = true;
for (int m = 0; m < structureWidth; m++)
{
for (int n = 0; n < structureHeight; n++)
{
Color pixel = normalisedImage.GetPixel(
Math.Min(
Math.Max(
0,
i + m - structureWidth / 2),
erodedImage.Width - 1),
Math.Min(
Math.Max(
0,
j + n - structureHeight / 2),
erodedImage.Height - 1));
bool pixelSet = ColoursEqual(
pixel,
Color.White);

if ((pixelSet != structure[m, n]) &&
(structure[m, n] != false))
{
keep = false;
break;
}
}
}

erodedImage.SetPixel(
i,
j,
keep ? Color.White : Color.Black);
}
}

return erodedImage;
}

private double GetCr(Color pixel)
{
return 128 +
0.5f * (double)pixel.R -
0.418688f * (double)pixel.G -
0.081312f * (double)pixel.B;
}

private double GetCb(Color pixel)
{
return 128 -
0.168736f * (double)pixel.R -
0.331264f * (double)pixel.G +
0.5f * (double)pixel.B;
}

public bool IsSkin(Color pixel)
{
int Cb = (int)((this.GetCb(pixel)/256) * 400);
int Cr = (int)((this.GetCr(pixel)/256) * 400);

return (ColoursEqual(
this.skinColourSpace.GetPixel(Cb, Cr),
Color.White));
}
}
}

To be continued...

Saturday, 18 June 2011

Interactive Plays - a 2D game engine

Back in September 2010, I spoke about some of the projects I was working on and mentioned a 2D game engine. This year I decided to focus on this project as my main project for the year. Here is a brief description of my plan and how I'm getting on with it.


System Metaphor - Interactive Play

I started by thinking about a metaphor to describe what it was I was trying to create. When I thought about 2D point-click style games (especially Role-Playing Games) I realised that they were all telling a story of some kind so I started thinking about other ways in which people tell stories. Eventually I settled on Plays. I then started mapping some of the terminology of a play with the terminology of a game e.g.

Theatre = Computer
Stage = Screen
Prop = Interactive Sprite
Stage Directions = Events and Actions
etc.

I used a mind map tool to visualise my ideas around the metaphor and to help lead into a high level design. The mind map tool I used was freemind - http://freemind.sourceforge.net/wiki/index.php/Main_Page.

Three-year Plan

Before jumping into the design I tried to roughly plan out my strategy for the next three years of the project.

Year 1 - Build interactive play engine
Year 2 - Build first game using engine
Year 3 - Build follow up game and distribute first game

I also looked at the amount of spare time I would allocate to working on the project, how long each sprint was going to be and what my ideal timebox for the first year would be.

Again I used the mind mapping tool to visual my ideas around this plan.

Sprint 0 - High level design

Using the mapping of terminology I produced whilst drawing up the system metaphor I put together a rough collection of classes in a UML class diagram. I then took each in turn and tried to think of roughly what responsibilities and interactions they would have. As this was sprint 0 I did not want to go into too much detail on the design. I decided that I would build an XML based language that would describe the interactive plays to the game engine with a future project being an editor that would allow visual production of the XML file.

I used a freeware UML tool called Violet to produce the high level design diagrams - http://alexdp.free.fr/violetumleditor/page.php?id=en:home.

During the sprint 0 I put together the user stories that I wanted to tackle first and epic user stories for the rest. I detailed user stories that I felt would cover about 2-3 sprints and kept the rest vague. I planned out the release roughly by placing the user stories and epics into sprints as rough place holders (to be detailed more accurately during the sprint planning for each sprint). I set my initial sprint capacity to the number of days I would be working on the project per sprint and estimated the user stories and epics in number of days to begin with. I used the community edition of Rally to manage my user stories and epics - http://www.rallydev.com/index.php (the main reason for this is that I am familiar with Rally from using the commercial version at work).

I also looked at all of the tools I would need and invested some time working out how to piece them together. Here are a few examples:

* Visual Studio 2010 Express Edition
* Rally Community Edition
* Gendarme and Stylecop for static code analysis (Had to figure out integration with Visual Studio so that they were run on every build)
* NUnit for Test Driven Development and Automated Acceptance Tests
* MoMA for portability checking (Mono compatible)
* InkScape for building Artwork
* Krystal recording studio for music and sound effects
etc.

I also figured out a backup strategy so I wouldn't lose anything.

Sprint Planning

Initially I started by estimating in days (or more to the point evenings) but after a few sprints I started to have a good indication of my velocity which allowed me to see clearly how much capacity I have to fit user stories into. My estimates then became story points using typical small, medium and large user stories to compare a new user story to when estimating.

I continue to monitor my velocity using Rally's velocity chart and work out my next sprint capacity based on the worst 3 sprints. At the moment my velocity and capacity has dropped considerably due to having less time to work on the project through the week.

As I approach an epic that I have not broken into smaller user stories I try to break it down as much as possible and estimate each user story. I then attempt to release plan the user stories by putting them into future sprints as place holders for where I would like to start tackling them.

During this process I am able to see how good/bad my progress is on the overall release and can start thinking about how to adjust the release to meet my goals. In my case I can only extend the timebox because I don't have any more people who can work on it and the scope is reasonably fixed as there are a lot of mandatory user stories to provide a viable release.

Sprint Implementation - TDD and Acceptance Testing

During implementation of the user stories I take a Test Driven Development approach:

* Write a failing test
* Implement only what is needed to make the test pass
* Refactor

During the refactoring step I make heavy use of the static code analysis tools as well as looking for opportunities to make use of design patterns.

Once I'm happy that I have created tests that cover everything for that user story I generate an acceptance test for the user story and ensure that it passes.

I will also take a look at the code coverage of the tests to ensure I have a high coverage (I currently have a test coverage of 91%). Whilst this test coverage shows me the amount of code I am running during the test it does not mean I am fully testing the code being run therefore I only use it as an indicator of potential problems. I make use of a tool called partcover to get this information - http://partcover.blogspot.com/

Sprint Review

At the end of each sprint I look over what I have achieved and what I have missed. I will update the backlog of user stories and may even revise some estimates. I also spend some time doing some manual testing to make sure I am definitely happy with accepting the user story.

Current Progress

I am just about to finish sprint 7 and have another 8 sprints to go before the end of the timebox as it currently stands. My velocity has dropped considerably over the past couple of sprints and I'm currently averaging at 2.5 points. At this velocity I will not complete the mandatory user stories in the current timebox so I will need to revise my overall plan and decide how to improve my current progress.


I currently have 108 unit and acceptance tests all passing and 91% code coverage from my tests. I'm working on Animated Scenery at the moment.

My sprints cover 3 weeks but I only have 9 hours per week to spend on the project so essentially my one sprint is only 3 days worth of capacity so I only have two options to improve my current progress - Increase the amount of time I spend on the project each week or extend the timebox. Currently I'm leaning towards extending the timebox.



Thursday, 23 December 2010

Snowpocalypse 2010


Some images of the snow and the gridlock it created this year.


















Movember 2010






















My friends on facebook and colleagues at work will be well aware that I joined a Movember team this year and grew a moustache to raise awareness and money for prostate cancer.

The team managed to collect £627 which will support the prostate cancer charity and the Everyman campaign. This year Movember raised almost 9 million pound in the uk alone with almost 112,000 people getting involved. For details, pictures and videos please take a look at my mospace.

I'd like to thank everyone involved and all those who donated.




Sunday, 21 November 2010

My thoughts on Test Driven Development


A few years back my work decided to roll out the use of Scrum to manage the teams of developers. This has worked well for the most part but we have so far not taken on any of the XP techniques that most Agile Scrum teams are using. This will soon change as a continuous integration system is being built and Test Driven Development (TDD) is beginning to be rolled out.

With the start of the TDD roll out, Clarke Ching (our Agile Expert and Consultant) has pointed us in the direction of his TDD Test Drive which uses a simple example with Excel and VB to introduce the principals of TDD.

My basic understanding of TDD is that the development process changes to:

1. Write an automated test that fails
2. Write just enough code to make it pass
3. Look for opportunities to re-factor the code
4. Make sure all the tests still pass
5. Repeat steps 1-4 until all tests are written and pass.

My initial thoughts on TDD are that whilst bringing huge benefits over traditional manual unit testing (especially where we have a large number of versions of the software being maintained using branches and roll ups), I am worried about missing important tests that will drive the software in the wrong direction. I am also worried about how to apply it to legacy code - There could be a large amount of re-factoring required which will impact our delivery time.

What I mean by missing important tests is that the tests are often based on the requirements or description of a bug that has been found in the software. Most of the time requirements and bug descriptions are vague or do not tell the whole story - if these are the sole drivers of the tests and the code is only written to make these tests pass it could be easy to miss something important.

I'd love to hear from other software developers on their thoughts and experiences with TDD and I'll let you know how I get on when I start putting it into practice.



Trip round Scotland 2010


My partner David and I's friend Matt from Bournemouth was visiting us a while back so we decided to give him a little tour around some of Scotland.

We took a drive up through the Rannoch Moor and on to a hotel just outside Fort William. We have nicknamed Rannoch Moor, Jurassic Park and whilst it was raining heavily it was still a great place to drive through.
EDIT: It was pointed out to me that the picture above is actually taken in Glencoe which is just outside the Rannoch moor.

The next day we followed the sat-nav (Bad idea) over to the Balmoral Estate (The Royal Families Scottish Holiday Home) and took a tour. The sat-nav took us straight up and over the Lecht which is a Scottish Ski resort and there was quite a bit of snow in the area. We ended up on a single track road for quite a few miles before finally coming out just down the road from Balmoral.

On the last day we took a trip down to Inveraray and visited the 19th Century jail and court house which has been turned into a museum.

It was a great few days away and I've included some links for anyone who wants to see these places for themselves.


Team Building Event


Back in September my work decided to have a team building event. I'm not usually a fan of team building events and they had certainly picked the worst day for it given the weather but in the end it was really quite good.

Our team started off quite badly losing several events in a row - Lowering a bamboo stick with the tops of your fingers, trying to grab and move a bottle from a distance with rope, tape, etc. and using tubes and barrels to keep a tennis ball rolling for as long as we possibly could.


By the afternoon our luck had changed and we started to win a few events - Obstacle course where you couldn't stand on the grass (using logs instead), building a catapult, building a tent blindfolded, mini highland games.

We finally moved indoors and out of the rain but the events were not over - NASA quiz, Build a bridge for a radio controlled car out of paper and tape.

In the end we came in joint fourth which was quite good considering how we started out.


We all then got the chance to do some archery, laser clay pigeon shooting and some other events to round off the day. Overall it was a good day despite the pouring rain.