# EmguCV: Detect a ball in the frame

I am having a VERY hard time capturing when the ball comes into frame in this video

I have no idea what to set the parameters too, and trying random values doesn't seem to help at all, I can't see the pattern to know what effect the numbers are having. This is what I'm attempting.

Background subtraction, or color detection won't work, as they could easily change. I need a more generalized solution.

var laneSixBedRect = new Rectangle(new Point(240, 185), new Size(240, 150));
var laneSixBed = imgSource.GetSubRect(laneSixBedRect);

TrackShot(laneSixBed);

private static void TrackShot(Image<Bgr, byte> laneBed)
{
var laneBedGray = laneBed.Convert<Gray, byte>();

var circles = laneBedGray.HoughCircles(
new Gray(150),  //cannyThreshold
new Gray(75),   //circleAccumulatorThreshold
2.0,            //Resolution of the accumulator used to detect centers of the circles
20.0,           //min distance
)[0];           //Get the circles from the first channel

foreach (CircleF circle in circles)
laneBed.Draw(circle, new Bgr(Color.Brown), 2);
}


Edit: This is my currentTrackShot method, it's running about 70% as far as accuracy, still some false positives, and some missed positives.

    private static void TrackShot(Rectangle laneRect, Image<Bgr, byte> prevImage, Image<Bgr, byte> currImage, Image<Bgr, byte> background)
{
var laneBedBack = background.GetSubRect(laneRect);
var laneBedPrev = prevImage.GetSubRect(laneRect);
var laneBedCurr = currImage.GetSubRect(laneRect);

var laneBedBackGray = laneBedBack.Convert<Gray, byte>();
//TODO: Should these be Smoothed?
var laneBedPrevGray = laneBedPrev.Convert<Gray, byte>().SmoothGaussian(5);
var laneBedCurrGray = laneBedCurr.Convert<Gray, byte>().SmoothGaussian(5);

//TODO: Uncomment to see difference between frames, nearly black when no motion
//var diff = laneBedPrevGray.AbsDiff(laneBedCurrGray);
//diff.Convert<Bgr, byte>().CopyTo(laneBedCurr);

//TODO: Improve these values
var prevFeatures = laneBedPrevGray.GoodFeaturesToTrack(100, .01, .1, 3)[0];

var returnFeatures = new PointF[1];
byte[] status;
float[] trackError;
OpticalFlow.PyrLK(laneBedPrevGray, laneBedCurrGray, prevFeatures, new Size(15, 15), 5, new MCvTermCriteria(5), out returnFeatures, out status, out trackError);

//TODO: Now how do I refine this???
for (var i = 0; i < returnFeatures.Length; i++)
{
var prevPoint = prevFeatures[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));
if (state == 1 && line.Length > 15 && error < 10)
{
laneBedCurr.Draw(line, new Bgr(Color.Green), 3);
Console.WriteLine("E: {0}", error);
Console.WriteLine("L: {0}", line.Length);
}
}

viewerModified.Image = currImage;
}


EDIT2: My ulimate goal is to be able to draw a line along the trajectory the ball took and store that trajectory in some fashion that can be compared to others.

## Remove things you don't want

Since the camera is static, you might want to use a background remover first. I found that the standard one provided with OpenCV works pretty well. I create it like this in the Android OpenCV SDK (you can play with the parameters) :

backgroundSubtractor = new BackgroundSubtractorMOG(3, 4, 0.8);


Then, apply it to each image in your video (no need to re-instantiate it unless you move the camera, it will learn from the sequence of images).

## Computing the motion

First, using the Hough Transform for fast-moving shapes isn't very useful. The Hough transform requires you to be able to detect the shape's boundary with some accuracy, which obviously you can't, thanks to the motion blur.

I would suggest looking into algorithms for computing the optical flow. I don't know how close EmguCV is to the original OpenCV, but you could try calcOpticalFlowPyrLK (computes the flow for a set of points in the image, usually obtained using the goodFeaturesToTrack method) or calcOpticalFlowFarneback (computes a dense flow for the whole image, but more CPU-hungry).

Additionally, there have been some people working on CUDA/GLSL versions of Lucas-Kanade (the first one) if you really want to have a fast, dense flow algorithm, but I haven't seen a lot of useful implementations.

See the OpenCV documentation here : http://opencv.willowgarage.com/documentation/cpp/motion_analysis_and_object_tracking.html#calcOpticalFlowPyrLK

• EmguCV is just a C# wrapper for OpenCV, it seems to have most everything covered. – CaffGeek Sep 11 '12 at 19:02
• Then you're probably okay with that! Does your camera move, or is it static? It's much, much easier for the latter! – F.X. Sep 11 '12 at 19:04
• It will be static. However, there could be other things moving in the image. But that's a problem for later. Right now I just want to detect the motion of a ball moving in the frame. – CaffGeek Sep 11 '12 at 19:08
• See updated answer then, you might want to use the background removed included in OpenCV before doing any work! – F.X. Sep 11 '12 at 19:17
• Since the camera is static, you should be able to leverage prior knowledge, such as the fact that the balls only move through fixed planes, namely the alley. – Maurits Sep 11 '12 at 19:20