2

I am working on a people counter. For this I have the Microsoft Kinect installed over the door. I am working with C# and EmguCV. I have extracted the heads of the people, so that they appear as white blobs on a black image. Then I have created a bounding box around the heads. That works fine. So I now how many blobs I have per frame and I also now their position. This works fine. But now I want to track the blobs because I want to count how much people come in and go out, but I don't know how to do this. Can anyone help me? The problem is that every frame, new blobs can appear and old blobs can disappear. Can anyone give me an algorithm or maybe some code? or a paper. Thanks a lot!


Sure. This is the code for the blobs:

using (MemStorage stor = new MemStorage())
        {



            Contour<System.Drawing.Point> contours = head_image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_SIMPLE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_EXTERNAL, stor);



            for (int i = 0; contours != null; contours = contours.HNext)
            {

                i++;



                //if ((contours.Area > Math.Pow(sliderMinSize.Value, 2)) && (contours.Area < Math.Pow(sliderMaxSize.Value, 2)))
                {

                    MCvBox2D box = contours.GetMinAreaRect();

                    blobCount++;

                    contour_image.Draw(box, new Bgr(System.Drawing.Color.Red), 1);


                    new_position = new System.Drawing.Point((int)(box.center.X), (int)(box.center.Y));
                    new_x = box.center.X;
                    new_y = box.center.Y;
                }

            }
        }
Shog9
  • 156,901
  • 35
  • 231
  • 235
Lisi
  • 31
  • 2
  • 5

1 Answers1

1

Please see Emgu CV Blob Detection for more information. Assuming you are using Emgu CV 2.1 or higher, then the answer will work. If you are using version 1.5 or higher, see this thread on how to easily detect blobs. Or look at the code below

     Capture capture = new Capture();

     ImageViewer viewer = new ImageViewer();

     BlobTrackerAutoParam param = new BlobTrackerAutoParam();
     param.ForgroundDetector = new ForgroundDetector(Emgu.CV.CvEnum.FORGROUND_DETECTOR_TYPE.FGD);
     param.FGTrainFrames = 10;
     BlobTrackerAuto tracker = new BlobTrackerAuto(param);

     Application.Idle += new EventHandler(delegate(object sender, EventArgs e)
     {
        tracker.Process(capture.QuerySmallFrame().PyrUp());
        Image<Gray, Byte> img = tracker.GetForgroundMask();
        //viewer.Image = tracker.GetForgroundMask();

        MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0);
        foreach (MCvBlob blob in tracker)
        {
           img.Draw(Rectangle.Round(blob), new Gray(255.0), 2);
           img.Draw(blob.ID.ToString(), ref font, Point.Round(blob.Center), new Gray(255.0));
        }
        viewer.Image = img;
     });
     viewer.ShowDialog();

Hope this helps!

EDIT

I think you should use this code every ten frames or so (~3 times a second) and do something like this:

     Capture capture = new Capture();

     ImageViewer viewer = new ImageViewer();

     BlobTrackerAutoParam param = new BlobTrackerAutoParam();
     param.ForgroundDetector = new ForgroundDetector(Emgu.CV.CvEnum.FORGROUND_DETECTOR_TYPE.FGD);
     param.FGTrainFrames = 10;
     BlobTrackerAuto tracker = new BlobTrackerAuto(param);
     int frames = 0;
     Application.Idle += new EventHandler(delegate(object sender, EventArgs e)
     {
        frames++;//Add to number of frames
        if (frames == 10)
        {
        frames = 0;//if it is after 10 frames, do processing and reset frames to 0
        tracker.Process(capture.QuerySmallFrame().PyrUp());
        Image<Gray, Byte> img = tracker.GetForgroundMask();
        //viewer.Image = tracker.GetForgroundMask();

        int blobs = 0;

        MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0);
        foreach (MCvBlob blob in tracker)
        {
           //img.Draw(Rectangle.Round(blob), new Gray(255.0), 2);
           //img.Draw(blob.ID.ToString(), ref font, Point.Round(blob.Center), new Gray(255.0));
           //Only uncomment these if you want to draw a rectangle around the blob and add text
           blobs++;//count each blob
        }
        blobs = /*your counter here*/;
        blobs = 0; //reset 
        viewer.Image = img;//get next frame
     });
     viewer.ShowDialog();

EDIT 2

It sounds like you just want to identify the blobs, it sounds like you want McvBlob.ID. This is the ID of the blob and you can check which ID's are still there and which are not. I would still do this every ten frames to not slow it down as much. You just need a simple algorithm that can observe what the ID's are, and if they have changed. I would store the IDs in a List<string> and check that list for changes every few frames. Example:

List<string> LastFrameIDs, CurrentFrameIDs;

         Capture capture = new Capture();

     ImageViewer viewer = new ImageViewer();

     BlobTrackerAutoParam param = new BlobTrackerAutoParam();
     param.ForgroundDetector = new ForgroundDetector(Emgu.CV.CvEnum.FORGROUND_DETECTOR_TYPE.FGD);
     param.FGTrainFrames = 10;
     BlobTrackerAuto tracker = new BlobTrackerAuto(param);
     int frames = 0;
     Application.Idle += new EventHandler(delegate(object sender, EventArgs e)
     {
        frames++;//Add to number of frames
        if (frames == 10)
        {
        frames = 0;//if it is after 10 frames, do processing and reset frames to 0
        tracker.Process(capture.QuerySmallFrame().PyrUp());
        Image<Gray, Byte> img = tracker.GetForgroundMask();
        //viewer.Image = tracker.GetForgroundMask();

        int blobs = 0, i = 0;

        MCvFont font = new MCvFont(Emgu.CV.CvEnum.FONT.CV_FONT_HERSHEY_SIMPLEX, 1.0, 1.0);
        foreach (MCvBlob blob in tracker)
        {
           i++;
           //img.Draw(Rectangle.Round(blob), new Gray(255.0), 2);
           //img.Draw(blob.ID.ToString(), ref font, Point.Round(blob.Center), new Gray(255.0));
           //Only uncomment these if you want to draw a rectangle around the blob and add text
           CurrentFrameIDs.Add(blob.ID.ToString());
           if (CurrentFrameIDs[i] == LastFrameIDs[i])
               img.Draw(Rectangle.Round(blob), new Gray(0,0), 2);//mark the new/changed blob
           blobs++;//count each blob
        }
        blobs = /*your counter here*/;
        blobs = 0; //reset 
        i = 0;
        LastFrameIDs = CurrentFrameIDs;
        CurrentFrameIDs = null;
        viewer.Image = img;//get next frame
     });
     viewer.ShowDialog();
Community
  • 1
  • 1
Kinected
  • 441
  • 5
  • 19
  • Thanks for the answer. I am using 2.1 or higher. Does this mean that I can use the code you have posted? I don't understand the code. How does it work? Should it be executed every frame and if so, how does this knows if the blob has the same id as in the following image and if blobs leave the image or appear in the image? – Lisi Jan 08 '13 at 03:06
  • You can still use the code I have posted, and the thread says that some users had problems with the speed of the processing using this algorithm – Kinected Jan 08 '13 at 03:08
  • ok thanks a lot :) but how does it work? should this be executed each frame? don't i have to safe the old blobs to compare them with the new? can i draw the trajectories with this method? – Lisi Jan 08 '13 at 03:26
  • You do have to save the old blobs, and I would activate this every few frames for performance or every frame for accuracy – Kinected Jan 08 '13 at 05:02
  • So this is no tracker? This is only a method for finding blobs or not? but I have already drawn rectangles around my blob so where is the difference to my code? – Lisi Jan 08 '13 at 13:32
  • This automatically runs every frame because it is an event handler assigned to `Application.Idle`, and it draws a rectangle around the blob. All you have to do is count that amount of them in the frame. Check edits – Kinected Jan 08 '13 at 13:55
  • but I have already the number of blobs in the frame and I also have the rectangle around the blob. The problem I have is that I want to now which blobs in the current frame belongs to which blob in the last frame, especially if a blob leaves the image or is new. For example in the last frame there were blob A, B and C and in the current one there are blob A, B and D so that C leaves the image and D enters the image. How do I know which one leaves, which one is new and which of the blobs belong to which one. – Lisi Jan 08 '13 at 14:03