Question

I have a noisy image where I have to detect circles of specific sizes. On few images, there might be very fine line-cuts. Currently the algorithm I use is basically if both the exterior(black) and interior central (white) circles are not detected in contour based circle detection, I declare that there's a line cut. But this method doesn't always work. Also detection of fine lines is difficult (the line on the background surface is by default which should not be detected).enter image description here

Pseudo code for the circle detection and line cut

1. convert image to grey scale
2. find hough circles
3. from the circles found, store the ones with expected radii.
4. apply canny to the grey scale image and dilate.
5. find contours on the canny image.
6. check if contour is circle :

if(contour.size() > lineThresh) {
    cv::RotatedRect rect = cv::fitEllipse(contour);
    float width = rect.size.width * 0.5;
    float height = rect.size.height * 0.5;

    float shortAxis = 0.0;
    float longAxis = 0.0;

    if (width < height) {
        shortAxis = width;
        longAxis = height;
    } else {
        shortAxis = height;
        longAxis = width;
    }

    if (longAxis == 0.0) {
        longAxis = 1.0;
    }

    float circleMeasure = ((longAxis - shortAxis) / longAxis);
    float radius = (longAxis + shortAxis) / 2;

    float perimeter = cv::arcLength(contour, false);
    float area = abs(cv::contourArea(contour));

    if (area <= 0) {
        area = 1;
    }
    float area_diff = std::abs(area - ((radius * perimeter) / 2));
    float area_delta = area_diff / area;

    if(circleMeasure < this->circleError &&
            area_delta < this->areaDelta) {
        return true;
    }else
                return false;

7. if both (exterior and interior central) circles are found, circles are good
   else if, found in hough and not in contours, there's a line cut.

This is the image I get after dilating. Is there any good way of detecting line in this?enter image description here

Was it helpful?

Solution

Ok guys found a solution finally!

- Use tophat morphology on the gray image. This enhances the line cuts along with noise
- Use line filter and rotate it by 10 degrees.
  e.g. Mat kernel = (cv::Mat_<float>(3, 3) << -1, 4, -1,
                                              -1, 4, -1,
                                              -1, 4, -1;
  (Now only the straight contours remain)     
- Check the aspect ratio of the contours and store if it exceeds a threshold.
- Check for collinearity of the contours. If the length of collinear segment is more than a threshold, declare it as a line cut. 

This algorithm is working good for me

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top