Ball Detection Noise


I am attempting to detect a yellow ball (as seen here) using the hough circle transform. However, after applying my mask using inRange, I still have a lot of noise and the hough circle transform is detecting non-existent circles.

Here is an image with the mask applied.

My HSV values are:
lower - 20, 0, 100
upper - 40, 255, 255

Thank you in advanced for your help!

I couldn’t reproduce your binary image with lower - 20, 0, 100 and upper - 40, 255, 255, I think you have done some mistakes. Please tell us what was your right values.

Btw i did these steps on your provided binary image :
1 - I did erosion on your binary image , so it removed most of noises from your image.
There is a good example for erosion operation in official docs

2- You can now find the ball circle with hough transform :

This is my my code . Hope it would be helpful.

Mat img = imread("/home/eaglesoft/Downloads/Screenshot (58).png");
Mat gray_img;
Mat erosion_dst;
int erosion_type = MORPH_RECT;
int erosion_size = 2;
Mat element = getStructuringElement( erosion_type,
Size( 2erosion_size + 1, 2erosion_size+1 ),
Point( erosion_size, erosion_size ) );
erode( gray_img, erosion_dst, element );
vector circles;
HoughCircles(erosion_dst, circles, HOUGH_GRADIENT, 1, img.rows/64, 200, 10,75, 120);
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(img, center, radius, Scalar(0, 0, 255), 2, 8, 0);

I investigated your picture some.

the issue here is that the background (wood) is very similar in color to your ball. you need a different ball or different background.

Do not forget, that HoughCircles also works with grayscale image so binarisation of image si not necessary.


CPP example:

// Read ball image
cv::Mat ball = cv::imread("ball.png");

// Convert ball image to grayscale
cv::Mat gray;
cv::cvtColor(ball, gray, cv::COLOR_BGR2GRAY);

// Detect ball
vector<cv::Vec3f> circles;
cv::HoughCircles(gray, circles, cv::HOUGH_GRADIENT, 1,
    gray.cols,  // Minimal circle distance set to width of frame to find only one ball
    100, 20, 
    70, // Minimal radius of ball [px]
    100 // Maximal radius of ball [px]

// Draw found circles
for (const auto& c: circles)
    cv::Point center = cv::Point(c[0], c[1]);
    // Circle center
    cv::circle(ball, center, 1, cv::Scalar(0, 0, UCHAR_MAX), 3, cv::LINE_AA);

    // Circle outline
    int radius = c[2];
    cv::circle(ball, center, radius, cv::Scalar(0, 0, 0), 2, cv::LINE_AA);
    cv::circle(ball, center, radius, cv::Scalar(UCHAR_MAX, UCHAR_MAX, UCHAR_MAX), 1, cv::LINE_AA);
1 Like