Hi all,

So recently I have been working on a ball tracking algorithm using OpenCV. It is actually not that hard to do and below I show the steps that I take while creating this and you can follow along too to make your own algorithm, the source code is at the end.

The first step is to load the video using the command

VideoCapture cap1(0);

Below is my video loaded using the imshow function.

Then I converted the image to HSV using the function

cvtColor(frame, frameHSV, CV_RGB2HSV);

and then split it into its individual channels into the array HSV

cvtColor(frame, frameHSV, CV_RGB2HSV); split(frameHSV, HSV);

and then I masked each of those channels to only detect values in a certain threshold in which the ball is visible. Below is the output for each of these channesl:

The white bits are when the color is in the threshold. I had adjusted the threshold values using the sliders above and thresholded using the function:

threshold(input, output , thresholdvalue, 255, 0);

Then I anded all these images using a bitwise operator and created 1 final image that could be used for ball tracking. The code for anding goes like:

bitwise_and(t[0], t[1], tr);

bitwise_and(tr, t[2], f);

and then I had also applied a Gaussian blur to help smooth the edges.

GaussianBlur(f, f, Size(9, 9), 2, 2);

here is the output:

As you can see only the rough shape of the ball is being shown.

Now I detected all circles in the image by using Houghs Transform. This is basically a function that can find lines and circles in an image. If you want to read up about it more you can do so here: https://stackoverflow.com/questions/4709725/explain-hough-transformation

I applied it using this code:

HoughCircles(f, circles, CV_HOUGH_GRADIENT, 1, 1000, para1, para2, 0, 1000);

and I drew the detected circles onto my initial image as shown here:

As you can see it tracks the ball well and I can get the coordinates of the ball for future manipulation.

One thing I do want to do is to be able to detect the distance of the ball from the computer by measuring the size of the circle, but as I have found the circles found by houghs transform can often be quite jumpy while tracking and do not always be the same size, so I think I will need to look for other alternatives to do this.

If you want to do this yourself too, here is the source code:

#include <opencv/cv.h>

#include <opencv2/highgui/highgui.hpp>

#include <opencv2/imgproc/imgproc.hpp>

#include <iostream>

using namespace cv;

using namespace std;

int main() {

VideoCapture cap1(0);

if (!cap1.isOpened()) {

cout << “cannot open camera”;

return -1;

}

double dWidth = cap1.get(CV_CAP_PROP_FRAME_WIDTH);

double dHeight = cap1.get(CV_CAP_PROP_FRAME_HEIGHT);

cout << “Frame size:” << dWidth << “x” << dHeight << endl;

namedWindow(“MyVideo”, CV_WINDOW_AUTOSIZE); //create a window called “MyVideo”

namedWindow(“f”, CV_WINDOW_AUTOSIZE);

namedWindow(“H”, CV_WINDOW_AUTOSIZE);

namedWindow(“S”, CV_WINDOW_AUTOSIZE);

namedWindow(“V”, CV_WINDOW_AUTOSIZE);

int htv, stv, vtv, para1, para2;

para1 = 200;

para2 = 50;

htv = 255;

stv = 170;

vtv = 255;

cvCreateTrackbar(“Ht”, “H”, &htv, 255);

cvCreateTrackbar(“St”, “S”, &stv, 255);

cvCreateTrackbar(“Vt”, “V”, &vtv, 255);

cvCreateTrackbar(“para1”, “f”, ¶1,300);

cvCreateTrackbar(“para2”, “f”, ¶2,50);

while (1)

{

Mat frame, frameHSV;

Mat HSV[3];

Mat t[3];

Mat tr;

Mat f;

bool bSuccess = cap1.read(frame);

if (!bSuccess)

{

cout << “Cannot read a frame from video stream” << endl;

break;

}

cvtColor(frame, frameHSV, CV_RGB2HSV);

split(frameHSV, HSV);

threshold(HSV[0], t[0] , htv, 255, 0);

threshold(HSV[1], t[1], stv, 255, 0);

threshold(HSV[2], t[2], vtv, 255, 0);

imshow(“H”, t[0]);

imshow(“S”, t[1]);

imshow(“V”, t[2]);

bitwise_and(t[0], t[1], tr);

bitwise_and(tr, t[2], f);

GaussianBlur(f, f, Size(9, 9), 2, 2);

vector<Vec3f> circles;

HoughCircles(f, circles, CV_HOUGH_GRADIENT, 1, 1000, para1, para2, 0, 1000);

for (size_t i = 0; i < circles.size(); i++)

{

Point center(cvRound(circles[i][0]), cvRound(circles[i][1]));

int radius = cvRound(circles[i][2]);

circle(frame, center, 3, Scalar(0, 255, 0), -1, 8, 0);

circle(frame, center, radius, Scalar(0, 0, 255), 3, 8, 0);

cout << “center : ” << center << “

radius : ” << radius << endl;

}

imshow(“f”, f);

imshow(“MyVideo”, frame);

if (waitKey(30) == 27)

{

cout << “esc key is pressed by user” << endl;

break;

}

}

return 0;

}