I am trying to detect the circles on some lunar craters images. Here are some examples:
After binarization, closing operation and removing noise, I ended up with such results:
I am now trying to fit the circles to the binarized images. I've decided to use OpenCV and HoughCircles()
method. I've found a very simple example on the official OpenCV website, so I've used it in my code:
import numpy as np
import cv2 as cv
img = cv.imread('binarized_image.jpg', cv.IMREAD_GRAYSCALE) #read the image
assert img is not None, "file could not be read, check with os.path.exists()" #check if file exists
img = cv.medianBlur(img,5)
cimg = cv.cvtColor(img,cv.COLOR_GRAY2BGR)
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,
param1=30,param2=15,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv.imshow('detected circles',cimg)
cv.waitKey(0)
cv.destroyAllWindows()
However, I am constantly ending up with error:
AttributeError: 'NoneType' object has no attribute 'rint'
It's the effect of line with circles = np.uint16(np.around(circles))
. It basically means, that my code did not detect ANY circles in the image. I've tried to modify param1
and param2
in the cv.HoughCircles
but none of the values seems to work. The results that I expect should be something like this:
How can I achieve this and detect the circles? How should I modify my code?
Your code works fine for me on Mac OSX Ventura. Note that I have added a line for cv.imwrite() to save the result to disk to show you.
Input:
import numpy as np
import cv2 as cv
img = cv.imread('binarized_image.jpg', cv.IMREAD_GRAYSCALE) #read the image
assert img is not None, "file could not be read, check with os.path.exists()" #check if file exists
img = cv.medianBlur(img,5)
cimg = cv.cvtColor(img,cv.COLOR_GRAY2BGR)
circles = cv.HoughCircles(img,cv.HOUGH_GRADIENT,1,20,
param1=30,param2=15,minRadius=0,maxRadius=0)
circles = np.uint16(np.around(circles))
for i in circles[0,:]:
# draw the outer circle
cv.circle(cimg,(i[0],i[1]),i[2],(0,255,0),2)
# draw the center of the circle
cv.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
cv.imshow('detected circles',cimg)
cv.imwrite('detected_circle.jpg',cimg)
cv.waitKey(0)
cv.destroyAllWindows()
Result:
ADDITION
Your other images need changes to detect the circles. You are currently not getting any circles, thus the error.
Change param2=15 to param2=7 and you can detect the smallest image.
I get:
For the larger image, change param2=15 to param2=13 and I get