Normaly houghtransfer uses mindistance between 2 circle centers but this does not work. included is my code and one of my lab results. I use multiple morphological steps to enhance the result.
My code:
-- coding: utf-8 --
""" Created on Mon Mar 2 14:22:03 2020
@author: Fabio Mirisola """
import numpy as np
import cv2 as cv
from skimage import morphology
# Import image
data = cv.imread("data.tif",cv.IMREAD_GRAYSCALE)
# Import background
background = cv.imread("background.tif",cv.IMREAD_GRAYSCALE)
# Subtracting background from data
cv_subt = cv.subtract(data,background)
# Cropping the image
Xcoord = 350
YCoord = 250
Width = 1330
Height = 1330
crop_img = cv_subt[YCoord:YCoord+Height, Xcoord:Xcoord+Width]
ret,thresh = cv.threshold(crop_img,25,255, cv.THRESH_BINARY)
# Removing small pixels
thresh_bool = thresh.astype('bool')
cleaned = morphology.remove_small_objects(thresh_bool, min_size=70, connectivity=5)
im_bin = cleaned.astype('uint8')
image = (im_bin)*255
# Inversing the image
ret,inverse = cv.threshold(image,5,255, cv.THRESH_BINARY_INV)
# Opening the holes
kernel = cv.getStructuringElement(shape=cv.MORPH_RECT, ksize=(4,4))
opening = cv.morphologyEx(inverse, cv.MORPH_OPEN, kernel, iterations = 3)
closing = cv.morphologyEx(opening, cv.MORPH_CLOSE, kernel, iterations = 1)
closing_bool = closing.astype('bool')
cleaned2 = morphology.remove_small_objects(thresh_bool, min_size=300, connectivity=400)
cleaned2_bin = cleaned2.astype('uint8')
image2 = (cleaned2_bin)*255
# Detected circles
circles = cv.HoughCircles(image2,3,cv.HOUGH_GRADIENT,1,30,param1=140,param2=45,minRadius=10,maxRadius=45)
circles = np.uint16(np.around(circles))
"""
Parameters 1 and 2 don't affect accuracy as such, more reliability.
Param 1 will set the sensitivity; how strong the edges of the circles need to be.
Too high and it won't detect anything, too low and it will find too much clutter.
Param 2 will set how many edge points it needs to find to declare that it's found a circle.
Again, too high will detect nothing, too low will declare anything to be a circle.
The ideal value of param 2 will be related to the circumference of the circles.
"""
#Drawing circles
detected = cv.cvtColor(crop_img,cv.COLOR_GRAY2BGR)
for i in circles[0,:]:
# draw the outer circle
cv.circle(detected,(i[0],i[1]),i[2],(0,255,0),1)
# draw the center of the circle
cv.circle(detected,(i[0],i[1]),2,(0,0,255),3)
#Show img
"""
cv.imshow("detected", detected)
cv.waitKey(0)
cv.destroyWindow("detected")
"""
#Save image
cv.imwrite("detected.jpg", detected)
C:\fakepath\detected.jpg In the picture you can see that it clearly detects the bubble correctly but then it detects is plenty more time.