I've got a video of a ball, I've done background subtraction (using MOG2) to isolate the change in the image. And I'm performing a blur to remove some of the noise caused by light/shadows/etc.

So, now that I have clearer image to work on, I'm using GoodFeaturesToTrack to and OpticalFlow.PyrLK to draw lines from frame to frame, to track the motion.

However, I still don't know how I can differentiate which motion is caused by a ball, and which is random, a person, etc... I'm just drawing lines tracking points that moved...but how do I determine which, if any, of those points were actually on the ball?

This is the code I currently have

class Program
    static Timer _myTimer;
    static Capture _capture;
    static ImageViewer _viewer;
    static readonly BackgroundSubtractorMOG2 MogDetector = new BackgroundSubtractorMOG2(0, 32.0f, true);
    static int _frameNumber;

    private static Image<Gray, byte> _previousFrame;
    private static PointF[] _previousFeatures;

    static void Main(string[] args)
        const int fps = 30;

        _myTimer = new Timer();
        _myTimer.Interval = 1000 / fps;
        _myTimer.Tick += MyTimerTick;

        _capture = new Capture(@"C:\source\dungeon\ComputerVision\Camera\App_Data\converted.avi");
        _viewer = new ImageViewer();

    private static void MyTimerTick(object sender, EventArgs e)
        var rawFrame = _capture.QueryFrame();
        var originalRoi = rawFrame.ROI;
        var roi = new Rectangle(0, rawFrame.Height / 2, rawFrame.Width, rawFrame.Height - rawFrame.Height / 2);

        var cropFrame = rawFrame
            .Convert<Gray, byte>()

        if (_frameNumber++ < 100) 
            MogDetector.Update(cropFrame.Convert<Bgr, byte>());
            MogDetector.Update(cropFrame.Convert<Bgr, byte>(), 1.0e-5);

        //Find the motion
        var motionMask = MogDetector.ForegroundMask
            .ThresholdBinary(new Gray(250), new Gray(255)) // Removes shadows
            //.Erode(3).Dilate(3) // Removes small artifacts that aren't really moving

        //var motion = frame.Copy(motionMask);
        //var motion = rawFrame.Add(motionMask);
        var motion = rawFrame.Copy();
        motion.ROI = roi;
        motion.Add(motionMask.Convert<Bgr, byte>());

        if (_previousFrame != null)
            PointF[] returnFeatures;
            byte[] status;
            float[] trackError;

            _previousFeatures = _previousFrame.GoodFeaturesToTrack(100, .01, .1, 3)[0];
            OpticalFlow.PyrLK(_previousFrame, motionMask, _previousFeatures, new Size(15, 15), 5, new MCvTermCriteria(5), out returnFeatures, out status, out trackError);

            //Console.WriteLine("Features Found:" + returnFeatures.Length);
            for (var i = 0; i < returnFeatures.Length; i++)
                var prevPoint = _previousFeatures[i];
                var currPoint = returnFeatures[i];
                var state = status[i];
                var error = trackError[i];

                var line = new LineSegment2D(new Point((int)prevPoint.X, (int)prevPoint.Y), new Point((int)currPoint.X, (int)currPoint.Y));
                var travelUp = prevPoint.Y - currPoint.Y;
                var travelLeft = prevPoint.X - currPoint.X;

                //if (state != 1 || !(line.Length > 15) || !(error < 10)) 
                if (!(state == 1 && line.Length > 15 && error < 10))

                motion.Draw(line, new Bgr(Color.Red), 3);
                Console.WriteLine("Error: {0}, Up: {1}, Left: {2}, Length: {3}", 
                    error, travelUp, travelLeft, line.Length);
        _previousFrame = motionMask;

        motion.ROI = originalRoi;
        _viewer.Image = motion;

A few other things that I'm struggling on are what the different thresholds, and values mean that I'm passing into GoodFeaturesToTrack, Mog2, etc, the documentation tends to just say "it's the threshold" ...


  • $\begingroup$ I'm reading en.wikipedia.org/wiki/Lucas%E2%80%93Kanade_method but the math...way way over my head. $\endgroup$ – CaffGeek May 28 '15 at 18:45
  • $\begingroup$ I think stackoverflow.com would be better place for the question $\endgroup$ – sagar May 30 '15 at 6:04
  • $\begingroup$ Why? It's not a question of code...It's a question about cv, I need help understanding how to find and track an object $\endgroup$ – CaffGeek May 30 '15 at 6:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.