Color tracking using EMGUcv

e_phi picture e_phi · Jun 3, 2014 · Viewed 8.9k times · Source

I am trying to make an colored object tracker which uses a binary image and blob detector to follow the target sort of like this: https://www.youtube.com/watch?v=9qky6g8NRmI . However I can not figure out how the ThresholdBinary() method work and if it is even the right one.

Here is a relevant bit of the code:

cam._SmoothGaussian(3);

blobDetector.Update(cam);
Image<Bgr,byte> binaryImage = cam.ThresholdBinary(new Bgr(145,0,145),new Bgr(0,0,0));
Image<Gray,byte> binaryImageGray = binaryImage.Conver<Gray,byte>();

blobTracker.Process(cam, binaryImageGray);

foreach (MCvBlob blob in blobTracker)
{
   cam.Draw((Rectangle)blob, new Bgr(0,0,255),2);
}

When I display the binaryImage I do not even get blobs. I just get a black image.

Answer

TC. picture TC. · Jun 3, 2014

Typically, the colored blob detection part of such an application works along the lines of:

  1. Convert the image to HSV (hue, saturation, value) color space.
  2. Filter the hue channel for all pixels with a hue value near the target value. Thresholding will typically give you all pixels with a value above or below the threshold. You are interested in the pixels near some target value.
  3. Filter the obtained mask some more, possibly using the saturation/value channels or by removing small blobs. Ideally only the target blob remains.

Some sample code that aims to find a green object (hue ~50) such as the green ball shown in the video:

// 1. Convert the image to HSV
using (Image<Hsv, byte> hsv = original.Convert<Hsv, byte>())
{
    // 2. Obtain the 3 channels (hue, saturation and value) that compose the HSV image
    Image<Gray, byte>[] channels = hsv.Split(); 

    try
    {
        // 3. Remove all pixels from the hue channel that are not in the range [40, 60]
        CvInvoke.cvInRangeS(channels[0], new Gray(40).MCvScalar, new Gray(60).MCvScalar, channels[0]);

        // 4. Display the result
        imageBox1.Image = channels[0];
    }
    finally
    {
        channels[1].Dispose();
        channels[2].Dispose();
    }
}