Simple object detection using OpenCV and machine learning

hfingler picture hfingler · Jun 20, 2011 · Viewed 58.7k times · Source

I have to code an object detector (in this case, a ball) using OpenCV. The problem is, every single search on google returns me something with FACE DETECTION in it. So i need help on where to start, what to use etc..

Some info:

  • The ball doesn't have a fixed color, it will probably be white, but it might change.
  • I HAVE to use machine learning, doesn't have to be a complex and reliable one, suggestion is KNN (which is WAY simpler and easier).
  • After all my searching, i found that calculating the histogram of samples ball-only images and teaching it to the ML could be useful, but my main concern here is that the ball size can and will change (closer and further from the camera) and i have no idea on what to pass to the ML to classify for me, i mean.. i can't (or can I?) just test every pixel of the image for every possible size (from, lets say, 5x5 to WxH) and hope to find a positive result.
  • There might be a non-uniform background, like people, cloth behind the ball and etc..
  • As I said, i have to use a ML algorithm, that means no Haar or Viola algorithms.
  • Also, I thought on using contours to find circles on a Canny'ed image, just have to find a way to transform a contour into a row of data to teach the KNN.

    So... suggestions?

    Thanks in advance. ;)

Answer

karlphillip picture karlphillip · Jun 20, 2011

Well, basically you need to detect circles. Have you seen cvHoughCircles()? Are you allowed to use it?

This page has good info on how detecting stuff with OpenCV. You might be more interested on section 2.5.

This is a small demo I just wrote to detect coins in this picture. Hopefully you can use some part of the code to your advantage.

Input: input img

Outputs: output opencv img

// compiled with: g++ circles.cpp -o circles `pkg-config --cflags --libs opencv`
#include <stdio.h>
#include <cv.h>
#include <highgui.h>
#include <math.h>

int main(int argc, char** argv)
{
    IplImage* img = NULL;

    if ((img = cvLoadImage(argv[1]))== 0)
    {
        printf("cvLoadImage failed\n");
    }

    IplImage* gray = cvCreateImage(cvGetSize(img), IPL_DEPTH_8U, 1);
    CvMemStorage* storage = cvCreateMemStorage(0);

    cvCvtColor(img, gray, CV_BGR2GRAY);

    // This is done so as to prevent a lot of false circles from being detected
    cvSmooth(gray, gray, CV_GAUSSIAN, 7, 7);

    IplImage* canny = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,1);
    IplImage* rgbcanny = cvCreateImage(cvGetSize(img),IPL_DEPTH_8U,3);
    cvCanny(gray, canny, 50, 100, 3);

    CvSeq* circles = cvHoughCircles(gray, storage, CV_HOUGH_GRADIENT, 1, gray->height/3, 250, 100);
    cvCvtColor(canny, rgbcanny, CV_GRAY2BGR);

    for (size_t i = 0; i < circles->total; i++)
    {
         // round the floats to an int
         float* p = (float*)cvGetSeqElem(circles, i);
         cv::Point center(cvRound(p[0]), cvRound(p[1]));
         int radius = cvRound(p[2]);

         // draw the circle center
         cvCircle(rgbcanny, center, 3, CV_RGB(0,255,0), -1, 8, 0 );

         // draw the circle outline
         cvCircle(rgbcanny, center, radius+1, CV_RGB(0,0,255), 2, 8, 0 );

         printf("x: %d y: %d r: %d\n",center.x,center.y, radius);
    }


    cvNamedWindow("circles", 1);
    cvShowImage("circles", rgbcanny);

    cvSaveImage("out.png", rgbcanny);
    cvWaitKey(0);

    return 0;
}

The detection of the circles depend a lot on the parameters of cvHoughCircles(). Note that in this demo I used Canny as well.