Click here to Skip to main content
Licence CPOL
First Posted 6 Jan 2011
Views 27,067
Downloads 3,037
Bookmarked 47 times

Detect and Track Objects in Live Webcam Video based on Color and Size by C#

By | 7 Jan 2011 | Article
Detect and track objects in live webcam video based on color and size by C#

Introduction

You can select a color in real time and it tracks that color object and gives you the position. I use aforge library for that. I also used .NET Framework 4.0. It is a C# desktop application, it can take up to 25 frames per second. You can change color size any time you want, the color of drawing point will also change.

Background

I saw a very interesting project in CodeProject name making of lego pit camera. With the help of this project, I thought a realtime tracker could be made where color and objects size could also be changed in real time. and can draw movement of that objects in a bitmap with that color. I use some part of their code, although I use separate color filter for more accuracy.

Using the Code

The steps of work are very simple:

  1. Take videoframe from webcam
  2. Use filtering by given color (here eucladianfiltering used)
  3. Make greyscale
  4. Find objects by given size
  5. Find biggest object
  6. Draw object position in bitmap

First, how my software works. It can start tracking by default color black and color range of 120 but you can change in real time to color change press that a color dialog will come, then select color, remember to press OK and see the solidcolor box that your required color is present or not.

To select the range and define minimum size of the object, see the next image, there are 3 numeric updown list for that. objectsize calculated in pixel now about the views:

There are 4 views, 3 of them are Aforge video source control and another one is a picturebox, the first one shows normal video, the second one shows all detected objects, the third box shows only the biggest object and the fourth one just draws a ’0' sign in biggest object location. See the below image for a clearer view:

I also added a richtextbox which shows the pixel of biggestrectangle position. Now about the code for connection, I use normal aforge connection code.

For that, you need to download aforge DLL, and also add a very good videocontrol for showing video you can add it in your toolbox. Just click freespace on toolbox chooseitems-> browse the DLL -> add the control.

using AForge;
using AForge.Video.DirectShow;

then initialize:

  videoDevices = new FilterInfoCollection(FilterCategory.VideoInputDevice);
               if (videoDevices.Count == 0)
                    throw new ApplicationException();
               foreach (FilterInfo device in videoDevices)
                {
VideoCaptureDevice videoSource = new VideoCaptureDevice(device.MonikerString);
 videoSource.DesiredFrameSize = new Size(320, 240);
 videoSource.DesiredFrameRate = 15;
videoSourcePlayer1.VideoSource = videoSource;
 videoSourcePlayer1.Start();
               }

For videoplayercontrol, add a event in its misc named:

 private void videoSourcePlayer1_NewFrame(object sender, ref Bitmap image)
        {//work with image
}

For understanding how filtering works, I will explain using a picture of a jellyfish. Here, I take a red center color for understanding. In my provided software, the user can choose his request color and size.

In that function, I apply my color detection code by writing Euclidean filtering and then use blobcounter to extract data. Here, I am explaining it.

So see EuclideanColorFiltering work, first see:

undefined

We are going to apply a color filter. It is very simple code to use euclideanfiltering:

// create filter
EuclideanColorFiltering filter = new EuclideanColorFiltering( );
// set center colol and radius
filter.CenterColor = Color.FromArgb( 215, 30, 30 );
filter.Radius = 100;
// apply the filter
filter.ApplyInPlace( image );

Now see the effect:

Well to understand how it works, look closely at the code:

filter.CenterColor = Color.FromArgb( 215, 30, 30 );
filter.Radius = 100;

The first line selects the select color value. You all know color has a value 0 to 255.
By filter.CenterColor = Color.FromArgb( 215, 30, 30 ); I specified my center color will be a red effected color because here value of red is 215, green and blue is 30, and filter.Radius = 100 means that all color value near 100 in my specified color.
Now my filter filters pixels, which color is inside/outside of RGB sphere with specified center and radius – it keeps pixels with colors inside/outside of the specified sphere and fills the rest with specified color.

Now for detect objects, I use bitmap data and use lockbits method to understand clearly this method see here. Then, we make it greyscale algorithom, then unlock it.

BitmapData objectsData = image.LockBits(new Rectangle
	(0, 0, image.Width, image.Height),ImageLockMode.ReadOnly, image.PixelFormat);
            // grayscaling
            UnmanagedImage grayImage = 
		grayscaleFilter.Apply(new UnmanagedImage(objectsData));
            // unlock image
            image.UnlockBits(objectsData);

Now for the object, we use blobcounter. It is a very strong class that aforge provided.

  blobCounter.MinWidth = 5;
  blobCounter.MinHeight = 5;
  blobCounter.FilterBlobs = true;
  blobCounter.ProcessImage(grayImage);
  Rectangle[] rects = blobCounter.GetObjectRectangles();
  foreach(Rectangle recs in rects)
  if (rects.Length > 0)
   {
      foreach (Rectangle objectRect in rects)
   {

      Graphics g = Graphics.FromImage(image);

    using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5))
                    {
                        g.DrawRectangle(pen, objectRect);
                    }

                    g.Dispose();
                }
            }

blobCounter.MinWidth and blobCounter.MinHeight define the smallest size of the object in pixel, and blobCounter.GetObjectRectangles() returns all the objects rectangle position, and using graphics class, I draw rectangle over the images.

Now, if you want to take only the biggest object, there is a method for that:

   blobCounter.MinWidth = 5;
   blobCounter.MinHeight = 5;
   blobCounter.FilterBlobs = true;
   blobCounter.ObjectsOrder = ObjectsOrder.Size;
  blobCounter.ProcessImage(grayImage);
  Rectangle[] rects = blobCounter.GetObjectRectangles();
  foreach(Rectangle recs in rects)
    if (rects.Length > 0)
            {
                   Rectangle objectRect = rects[0];
                    Graphics g = Graphics.FromImage(image);
                    using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5))
                    {
                        g.DrawRectangle(pen, objectRect);
                    }
                    g.Dispose();
                           }

Now image is like that:

But if you want to extract, you can use the following code:

Bitmap bmp = new Bitmap(rects[0].Width, rects[0].Height);
Graphics g = Graphics.FromImage(bmp);
g.DrawImage(c, 0, 0, rects[0], GraphicsUnit.Pixel);

So you will get your object like that:

undefined

For drawing the bitmap, I had to use threading. The thread was called in videosurecplayer event where I called the thread.

 void p(object r)
   {
       try
       {//create image
       Bitmap b = new Bitmap(pictureBox1.Image);
       Rectangle a = (Rectangle)r;
       Pen pen1 = new Pen(Color.FromArgb(160, 255, 160), 3);
       Graphics g2 = Graphics.FromImage(b);
       pen1 = new Pen(color, 3);
       SolidBrush b5 = new SolidBrush(color);
        Font f = new Font(Font, FontStyle.Bold);
       g2.DrawString("o", f, b5, a.Location);//draw the position
       g2.Dispose();
       pictureBox1.Image = (System.Drawing.Image)b;
       this.Invoke((MethodInvoker)delegate
           {
               richTextBox1.Text = a.Location.ToString() + 
				"\n" + richTextBox1.Text + "\n"; ;
           });
       }
       catch (Exception faa)
       {
           Thread.CurrentThread.Abort();
       }
      Thread.CurrentThread.Abort();
   }

I have to use invoke to write in textbox because of cross threading. To send rectangle object, I use parameterized thread. The thread 'aa' called the function "p()" to draw at bitmap and write in textbox.

 if (rects.Length > 0)
            {
                Rectangle objectRect = rects[0];

                // draw rectangle around derected object
                Graphics g = Graphics.FromImage(image);

                using (Pen pen = new Pen(Color.FromArgb(160, 255, 160), 5))
                {
                    g.DrawRectangle(pen, objectRect);
                }
              g.Dispose();
                int objectX = objectRect.X + objectRect.Width / 2 - image.Width / 2;
                int objectY = image.Height / 2 - (objectRect.Y + objectRect.Height / 2);
                ParameterizedThreadStart t = new ParameterizedThreadStart(p);
               Thread aa = new Thread(t);
               aa.Start(rects[0]);               
            }  

Points of Interest

Parameterized threading, cross threading has to implement here, also there is a need to apply invoke method for write using good threading, we can increase the framerate. About filtering Euclidian filtering is more accurate than HSLfiltering or Colorfiltering, yrbrcr filtering.

Thanks to Andrew Kirillov for his help.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

kdgupta87

Software Developer
Rymes
Bangladesh Bangladesh

Member

Follow on Twitter Follow on Twitter
Kishor is an undergraduate Computer Science and Engineering graduate from Khulna University Of Engineering and Technology. Currently working as a software developer in Rymes. Before joining Rymes Nascenia IT he worked as a software developer at Nascenia IT and as a trainee software developer at Technocrats BD, where he worked in .Net technologies. He developed few softwares in .Net framework. A few of the interesting ones were about face replacement, and GUI based requirement elicitation tool, image converter, image processing and LAN monitoring system.he worked on Ruby on Rails. Currently working on android
http://kishordgupta.wordpress.com/

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralMy vote of 5 PinmemberMember 85736886:28 24 Apr '12  
GeneralMy vote of 5 Pinmembersmejko800:06 17 Mar '12  
QuestionError PinmemberMember 79212685:26 25 Feb '12  
AnswerRe: Error PinmemberPrasanna17083:02 23 Mar '12  
GeneralRe: Error PinmemberMember 792126813:32 23 Mar '12  
Questionfunction of unlock bit? Pinmembermermaid0921:20 11 Nov '11  
QuestionThreading Pinmemberyaseen-khan14:05 16 May '11  
QuestionError PinmemberHasit Mistry3:08 10 Mar '11  
AnswerRe: Error Pinmemberanikmushfeki23:21 14 Aug '11  
Questionsuitable structure for a detected hand with color Pinmembersmile at life1:09 23 Feb '11  
AnswerRe: suitable structure for a detected hand with color Pinmemberkdgupta8711:27 23 Feb '11  
GeneralRe: suitable structure for a detected hand with color Pinmemberjasmine19890:56 24 Feb '11  
AnswerRe: suitable structure for a detected hand with color Pinmemberkdgupta873:41 24 Feb '11  
Questionwhy does the lightning make the detection fail ? Pinmemberjasmine19895:36 21 Feb '11  
AnswerRe: why does the lightning make the detection fail ? Pinmemberkdgupta8712:33 23 Feb '11  
GeneralRe: why does the lightning make the detection fail ? Pinmemberjasmine19890:51 24 Feb '11  
AnswerRe: why does the lightning make the detection fail ? Pinmemberkdgupta873:48 24 Feb '11  
GeneralMy vote of 5 Pinmembervikas amin9:24 7 Jan '11  
GeneralRe: My vote of 5 Pinmemberkdgupta879:35 7 Jan '11  
Generalnice one - have 5 PinmemberPranay Rana9:16 7 Jan '11  
GeneralRe: nice one - have 5 Pinmemberkdgupta879:37 7 Jan '11  
GeneralRe: nice one - have 5 PinmemberPranay Rana10:22 7 Jan '11  
General[My vote of 2] limit to red PinmemberAli Aboutalebi23:31 6 Jan '11  
GeneralRe: [My vote of 2] limit to red Pinmemberkdgupta870:03 7 Jan '11  
GeneralRe: [My vote of 2] limit to red PinmemberAli Aboutalebi0:08 7 Jan '11  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web04 | 2.5.120517.1 | Last Updated 7 Jan 2011
Article Copyright 2011 by kdgupta87
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid