Daniel
Daniel

Reputation: 11172

Finding partly hidden ball in OpenCV

I'm using OpenCV in an attempt of tracking a ball on a Bonzini table.

Converting the color to HSV and providing an upper and lower Scalar (25,90,90) and (30,255,255) I can find the ball when it is fully or almost fully visible.

The problem is when it is only partly visible. I tried to use HoughCircles to find the ball, but I'm not having any luck. While it is sometimes finding the ball, most of the time it just sees random circles everywhere - maybe this isn't the right way to go about it?

How do I locate the center of the ball when it is only partly visible (given that the radius of the ball is always the same)?

1]

HoughCircles code

Mat gray;

vector<Vec3f> circles;

bilateralFilter(frame, gray, 15, 1000, 1000);
cvtColor(gray, gray, COLOR_BGR2GRAY);
GaussianBlur(gray, gray, Size(9,9), 2, 2);

HoughCircles(gray, circles, HOUGH_GRADIENT, 1, 200, 50, 10, 12, 24);

Upvotes: 0

Views: 478

Answers (1)

alkasm
alkasm

Reputation: 23012

Occlusion is difficult in general to deal with, but having a fixed camera location gives you a little lee-way. You can easily calculate the trajectory of the ball from previous frames to know where it is likely to appear. If you use Hough circles, you can set param2 to be decently high so you're not getting false positives. Then whenever Hough circles doesn't detect a circle, i.e., circles is empty, you can use the prior frame positions to guess where the ball is during the occlusion.

If you're filtering your image by color, you will get a binary image which can be processed in a number of ways. Since you can calculate the ball size, you can easily use Hough circles in normal frames but this won't help you during occlusion; and template matching isn't likely to either. Instead, you'll need to use other approaches of grouping together those indicator points from your binary image.

Along the same lines you could not use Hough circles and just get the centers by looking for clustering with kmeans or similar in the binary image, and you can get the center of the cluster from that. The center could be compared with the predicted trajectory in some way. For example if the number of indicator pixels you get from your binary image filtering the yellow is too low, then you could simply rely on the predicted trajectory. Even more robust (I think) you could make a weighted average of the predicted trajectory with the center of the cluster, where the weight is given by the number of indicator pixels in the binary image. That way if you have no occlusion, you're getting most or all of the position based on the center of your indicator pixels; if you have some occlusion, you're adding a bit of correction via your supposed trajectory; and if you have a lot of occlusion, you can rely heavily on the predicted trajectory.

The above can similarly work with contours as well; again since you know the size of the ball, you can see how large your contours are with contourArea, and weight the center of your contours with your predicted trajectory based on the ratio of the contour area and the full circle area. @Green_Wizard's suggestion is also great for making sure you're finding contours in the right area. This is a reverse approach from my suggestion, where you look at the predicted trajectory first, and try to detect something in that limited area or sort indications by distance to that. I did something similar in a template matching project, but it was mostly for computational reduction---I defined an ROI based around the last known location of the template which grew in size until the template was found again. See for e.g.. I did not include predicted trajectory in this though as, at least for Mario, he doesn't actually move forward; the level moves backwards.

Upvotes: 1

Related Questions