The title of this article is a bit of acronym soup if you are not familiar with the technologies so let me explain.
In this article I will show you how to do generic computer vision blob tracking in Windows Presentation Foundation
using the emgu CV platform. Emgu CV is a great project that allows managed .NET applications to interact with the
powerful openCV computer vision platform.
Blob tracking in computer vision speak basically means tracking certain things around on the screen. In this example
those things are white blocks of color. This may sound kind of dumb; but it has a zillion applications such as tracking
human features, colored objects, animals in your yard, custom multi-touch rigs, extending
Kinect For Windows capability, and many many more applications.
Emgu CV comes with a great example on blob tracking called "video surveillance", but that implementation seems to be about tracking much more specific featured blobs.
My objective here is just to track groups of white pixels that show up in our images and accept or ignore them based on their size. As of Emgu CV version 2.4 the
cvblob library for generic blob tracking has
been in there, but there aren't any examples about how to use it.
In this example we will be taking raw input from either your systems default webcam or a provided transparent png. I have provided my own Visual Studio Express 2010 x64 c# wpf project in a download below without the
Emgu
CV dll's that you will need to obtain from the project download at sourcefourge.
The meat of this small application takes place in a
CompositionTarget.Rendering event that fires continuously and preforms actions on the image or on the webcam based on user selection.
Lets first look at the relevant Image blob detection code:
DOWNLOADS:
Download the Visual C# 2010 Express Example Application
WPF IMAGE CONVERSION CODE:
Drat,
Emgu CV operates on images in formats that cannot be easily displayed in WPF applications. No problem, we can fix that straight out of the
Emgu CV examples:
/// Convert an IImage to a WPF BitmapSource. The result can be used in the Set Property of Image.Source
private BitmapSource ToBitmapSource(IImage image)
{
using (System.Drawing.Bitmap source = image.Bitmap)
{
IntPtr ptr = source.GetHbitmap(); //obtain the Hbitmap
BitmapSource bs = System.Windows.Interop.Imaging.CreateBitmapSourceFromHBitmap(
ptr,
IntPtr.Zero,
Int32Rect.Empty,
System.Windows.Media.Imaging.BitmapSizeOptions.FromEmptyOptions());
DeleteObject(ptr); //release the HBitmap
return bs;
}
}
IMAGE BLOB DETECTION CODE:

// First we load in our image on the button press....
_blobsImg = new Emgu.CV.Image("photos/transparentBlobsTest.png");
// The in the main rendering event handler....
if (_blobsImg != null)
{
// This takes our nice looking color png and
// converts it to black and white
Image greyImg = _blobsImg.Convert();
// We again threshold it based on brightness...BUT WE INVERT THE PNG.
// BLOB DETECTOR DETECTS WHITE NOT BLACK
// this will esentially eliminate the color differences
// you could also do cool things like threshold only certain colors
// here for a color based blob detector
Image greyThreshImg = greyImg.ThresholdBinaryInv(new Gray(150), new Gray(255));
Emgu.CV.Cvb.CvBlobs resultingImgBlobs = new Emgu.CV.Cvb.CvBlobs();
Emgu.CV.Cvb.CvBlobDetector bDetect = new Emgu.CV.Cvb.CvBlobDetector();
uint numWebcamBlobsFound = bDetect.Detect(greyThreshImg, resultingImgBlobs);
// Here we can iterate through each blob and use the slider
// to set a threshold then draw a red box around it
Image blobImg = greyThreshImg.Convert();
Rgb red = new Rgb(255, 0, 0);
// Lets try and iterate the blobs?
foreach (Emgu.CV.Cvb.CvBlob targetBlob in resultingImgBlobs.Values)
{
// Only use blobs with area greater than some threshold
if (targetBlob.Area > _blobSizeThreshold)
{
blobImg.Draw(targetBlob.BoundingBox, red, 1);
}
}
// Does conversions so we can use wpf BitmapSources
BitmapSource wpfCompatibleInputSource = ToBitmapSource(_blobsImg);
BitmapSource wpfCompatibleThresholdSource = ToBitmapSource(greyThreshImg);
BitmapSource wpfCompatibleBlobSource = ToBitmapSource(blobImg);
originalImage.Source = wpfCompatibleInputSource;
thresholdImage.Source = wpfCompatibleThresholdSource;
blobtrackImage.Source = wpfCompatibleBlobSource;
}
One of the potential tiny problems with the image code is that in my greyscale conversions I am throwing out the transparency around the shapes so they all turn into squares.
WEBCAM BLOB DETECTION CODE:

// First we try to initialize the webcam on the button press....
_caper = new Emgu.CV.Capture();
// The in the main rendering event handler....
if (_caper != null)
{
// To avoid more conversions we need a grey image anyway.
// You can get a colored image with something fun like this:
// using (Image img = _caper.QueryFrame() )
using (Image webcamImg = _caper.QueryGrayFrame())
{
// This takes our nice looking input and blows or cuts off values
// above or below a bightness threshold
Image webcamThreshImg = webcamImg.ThresholdBinary(new Gray(150), new Gray(255));
// The magic blob detection code
Emgu.CV.Cvb.CvBlobs resultingWebcamBlobs = new Emgu.CV.Cvb.CvBlobs();
Emgu.CV.Cvb.CvBlobDetector bDetect = new Emgu.CV.Cvb.CvBlobDetector();
uint numWebcamBlobsFound = bDetect.Detect(webcamThreshImg, resultingWebcamBlobs);
// This is a simple way of just drawing all blobs reguardless of
// their size and not iterating through them
// It draws on top of whatever you input. I am inputting the threshold
// image. Specifying an alpha to draw with of 0.5 so its
// half transparent.
//Emgu.CV.Image blobImg = bDetect.DrawBlobs(webcamThreshImg, resultingWebcamBlobs, Emgu.CV.Cvb.CvBlobDetector.BlobRenderType.Default, 0.5);
// Here we can iterate through each blob and use the slider
// to set a threshold then draw a red box around it
Image blobImg = webcamThreshImg.Convert();
Rgb red = new Rgb(255, 0, 0);
// Lets try and iterate the blobs?
foreach (Emgu.CV.Cvb.CvBlob targetBlob in resultingWebcamBlobs.Values)
{
// Only use blobs with area greater than some threshold
if (targetBlob.Area > _blobSizeThreshold)
{
blobImg.Draw(targetBlob.BoundingBox, red, 1);
}
}
// Does conversions so we can use wpf BitmapSources
BitmapSource wpfCompatibleInputSource = ToBitmapSource(webcamImg);
BitmapSource wpfCompatibleThresholdSource = ToBitmapSource(webcamThreshImg);
BitmapSource wpfCompatibleBlobSource = ToBitmapSource(blobImg);
originalImage.Source = wpfCompatibleInputSource;
thresholdImage.Source = wpfCompatibleThresholdSource;
blobtrackImage.Source = wpfCompatibleBlobSource;
}
}