Use OpenCV to identiy hollow and filled circles

1k views Asked by At

I'm using OpenCV houghcircles to identify all the circles (both hollow and filled). Follow is my code:

import numpy as np
import cv2

img = cv2.imread('images/32x32.png')

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

bilateral = cv2.bilateralFilter(gray,10,50,50)

minDist = 30
param1 = 30
param2 = 50
minRadius = 5
maxRadius = 100

circles = cv2.HoughCircles(bilateral, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)

# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Test input image 1: enter image description here

Test output image1: enter image description here

As you can see I'm able identity most of the circles except for few. What am I missing here? I've tried varying the parameters but this is the best i could get.

Also, if I use even more compact circles the script does not identify any circles whatsoever.

enter image description here

3

There are 3 answers

2
cyborg On BEST ANSWER

An alternative idea is to use find contour method and chek whether the contour is a circle using appox as below.

import cv2

img = cv2.imread('32x32.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

inputImageCopy = img.copy()

# Find the circle blobs on the binary mask:
contours, hierarchy = cv2.findContours(gray, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Use a list to store the center and radius of the target circles:
detectedCircles = []

# Look for the outer contours:
for i, c in enumerate(contours):

    # Approximate the contour to a circle:
    (x, y), radius = cv2.minEnclosingCircle(c)

    peri = cv2.arcLength(c, True)
    approx = cv2.approxPolyDP(c, 0.02 * peri, True)
    
    if len(approx)>5: # check if the contour is circle
        
        # Compute the center and radius:
        center = (int(x), int(y))
        radius = int(radius)

        # Draw the circles:
        cv2.circle(inputImageCopy, center, radius, (0, 0, 255), 2)

        # Store the center and radius:
        detectedCircles.append([center, radius])

cv2.imshow("Circles", inputImageCopy)
cv2.waitKey(0)
cv2.destroyAllWindows()

enter image description here

enter image description here

2
toyota Supra On

I solved your problem. Using same code as your. No needed to modified. I changed value from 50 to 30. That all.

#!/usr/bin/python39
#OpenCV 4.5.5 Raspberry Pi 3/B/4B-w/4/8GB RAM, Bullseye,v11.
#Date: 19th April, 2022

import numpy as np
import cv2

img = cv2.imread('fill_circles.png')
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
bilateral = cv2.bilateralFilter(gray,10,50,50)

minDist = 30
param1 = 30
param2 = 30
minRadius = 5
maxRadius = 100

circles = cv2.HoughCircles(bilateral, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)

if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img, (i[0], i[1]), i[2], (0, 0, 255), 2)

cv2.imwrite('lego.png', img)
# Show result for testing:
cv2.imshow('img', img)
cv2.waitKey(0)
cv2.destroyAllWindows()

Output: enter image description here

0
fana On

If you can always get(or create from real image) such "clean" image, the bounding-box of the grid(2-dimensional array of circles) region can be easily obtained.

Therefore, you can know the rectangular area of interest (and the angle of rotation of the grid, if rotation is possible).

If you examine the pixels along the axial direction of the rectangle, you can easily find out how many circles are lined up and the diameter of the circle. Because lines that all pixel are black are gaps between adjacent row(or column). (Sum up the pixel values along the direction of the axis. Whether it is 0 or not tells you whether the line passes over the grid-cell or not.)

If necessary, you may check that the shape of the contour in each gird-cell is really circular.