Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

608
Views
EmguCV: Draw contour on object in Motion using Optical Flow?

I would like to do motion detection in C# (using EmguCV 3.0) to remove object in motion or in foreground to draw an overlay.

Here is a sample test I done with a Kinect (because It's a depth camera) Démo with Kinect

How can I get started with EmguCV 3.0 ?

  • I tried many background removal code that do not work
  • It seems OpticalFlow is a good start but there si no example in EmguCV 3.0
  • If I find the largest blob how can I find its contours ?

Can someone help me to get started ?

EDIT: 17/06/2015

In EmguCV3.0.0 RC I don't see OpticalFlow in the package and documentation: http://www.emgu.com/wiki/files/3.0.0-rc1/document/html/b72c032d-59ae-c36f-5e00-12f8d621dfb8.htm

There is only : DenseOpticalFlow, OpticalFlowDualTVL1 ???

This is a AbsDiff Code:

var grayFrame = frame.Convert<Gray, Byte>();
var motionFrame = grayFrame.AbsDiff(backFrame)
                           .ThresholdBinary(new Gray(20), new Gray(255))
                           .Erode(2) 
                           .Dilate(2);

Result: Demo Diff

I don't know how to get the motion in white ?

This is the Blob Code:

Image<Bgr, Byte> smoothedFrame = new Image<Bgr, byte>(frame.Size);
CvInvoke.GaussianBlur(frame, smoothedFrame, new Size(3, 3), 1); //filter out noises

Mat forgroundMask = new Mat();
fgDetector.Apply(smoothedFrame, forgroundMask);

CvBlobs blobs = new CvBlobs();
blobDetector.Detect(forgroundMask.ToImage<Gray, byte>(), blobs);
blobs.FilterByArea(400, int.MaxValue);
blobTracker.Update(blobs, 1.0, 0, 1);

foreach (var pair in blobs) {
  CvBlob b = pair.Value;
  CvInvoke.Rectangle(frame, b.BoundingBox, new MCvScalar(255.0, 255.0, 255.0), 2);
}

Result: Blob Demo

Why so much false positive ?

This is a MOG2 Code:

forgroundDetector.Apply(frame, forgroundMask);
motionHistory.Update(forgroundMask);
var motionMask = GetMotionMask();
Image<Bgr, Byte> motionImage = new Image<Bgr, byte>(motionMask.Size);
CvInvoke.InsertChannel(motionMask, motionImage, 0);

Rectangle[] rects;
using (VectorOfRect boundingRect = new VectorOfRect()) {
  motionHistory.GetMotionComponents(segMask, boundingRect);
  rects = boundingRect.ToArray();
}

foreach (Rectangle comp in rects) { ...

Result: MOG2 Demo

If I select the biggest Area how can I get the contour of the object ?

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

First, I can give you some example Optical Flow code.

Let oldImage and newImage be variables that hold the previous and current frame. In my code, it's of type Image<Gray, Byte>.

// prep containers for x and y vectors
Image<Gray, float> velx = new Image<Gray, float>(newImage.Size);
Image<Gray, float> vely = new Image<Gray, float>(newImage.Size);

// use the Horn and Schunck dense optical flow algorithm.
OpticalFlow.HS(oldImage, newImage, true, velx, vely, 0.1d, new MCvTermCriteria(100));

// color each pixel
Image<Hsv, Byte> coloredMotion = new Image<Hsv, Byte>(newImage.Size);
for (int i = 0; i < coloredMotion.Width; i++)
{
    for (int j = 0; j < coloredMotion.Height; j++)
    {
        // Pull the relevant intensities from the velx and vely matrices
        double velxHere = velx[j, i].Intensity;
        double velyHere = vely[j, i].Intensity;

        // Determine the color (i.e, the angle)
        double degrees = Math.Atan(velyHere / velxHere) / Math.PI * 90 + 45;
        if (velxHere < 0)
        {
            degrees += 90;
        }
        coloredMotion.Data[j, i, 0] = (Byte) degrees;
        coloredMotion.Data[j, i, 1] = 255;

        // Determine the intensity (i.e, the distance)
        double intensity = Math.Sqrt(velxHere * velxHere + velyHere * velyHere) * 10;
        coloredMotion.Data[j, i, 2] = (intensity > 255) ? 255 : intensity;
    }
}
// coloredMotion is now an image that shows intensity of motion by lightness
// and direction by color.

Regarding the larger question of how to remove the foreground:

If I had a way to get a static background image, that's the best way to start. Then, the foreground would be detected by the AbsDiff method and using Erode and Dilate or Gaussian to smooth the image, then use blob detection.

For simple foreground detection, I found Optical Flow to be way too much processing (8fps max), whereas the AbsDiff method was just as accurate but had no effect on framerate.

Regarding contours, if you're merely looking to find the size, position, and other moments, then the blob detection in the AbsDiff tutorial above seems to be sufficient, which uses Image.FindContours(...).

If not, I would start looking at the CvBlobDetector class as used in this tutorial. There's a built-in DrawBlob function that might come in handy.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!