Detect semicircle in OpenCV

Viewed 37100

I am trying to detect full circles and semicircles in an image.enter image description here

I am following the below mentioned procedure: Process image (including Canny edge detection). Find contours and draw them on an empty image, so that I can eliminate unwanted components (The processed image is exactly what I want). Detect circles using HoughCircles. And, this is what I get:

enter image description here

I tried varying the parameters in HoughCircles but the results are not consistent as it varies based on lighting and the position of circles in the image. I accept or reject a circle based on its size. So, the result is not acceptable. Also, I have a long list of "acceptable" circles. So, I need some allowance in the HoughCircle params. As for the full circles, it's easy - I can simply find the "roundness" of the contour. The problem is semicircles!

Please find the edited image before Hough transformenter image description here

6 Answers

@Micka's answer is great, here it is roughly translated into python

The method takes a thresholded image mask as an argument, leaving that part as an exercise for the reader

def get_circle_percentages(image):
    #compute distance transform of image
    dist = cv2.distanceTransform(image, cv2.DIST_L2, 0)
    rows = image.shape[0]
    circles = cv2.HoughCircles(image, cv2.HOUGH_GRADIENT, 1, rows / 8, 50, param1=50, param2=10, minRadius=40, maxRadius=90)      
    minInlierDist = 2.0
    for c in circles[0, :]:
        counter = 0
        inlier = 0

        center = (c[0], c[1])
        radius = c[2]

        maxInlierDist = radius/25.0

        if maxInlierDist < minInlierDist: maxInlierDist = minInlierDist

        for i in np.arange(0, 2*np.pi, 0.1):
            counter += 1
            x = center[0] + radius * np.cos(i)
            y = center[1] + radius * np.sin(i)

            if dist.item(int(y), int(x)) < maxInlierDist:
                inlier += 1
            print(str(100.0*inlier/counter) + ' percent of a circle with radius ' + str(radius) + " detected")
Related