Working with another type of threshold (an adaptive threshold that takes into account local proximity) will save you from your problem: an adaptive threshold result is what you are looking for.

[EDIT: I took the liberty of adding code to Hough circles. I admit that I played with the parameters for this single image to get a nice result, although I donโt know what type of accuracy you need for this type of problem]
import cv2 import numpy as np import matplotlib.pyplot as plt img = cv2.imread('image.png',0) thresh = cv2.threshold(img, 210, 255, cv2.ADAPTIVE_THRESH_MEAN_C)[1] canny = cv2.Canny(thresh,50,150) cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR) circles = cv2.HoughCircles(canny,cv2.HOUGH_GRADIENT,1,20, param1=50,param2=23,minRadius=0,maxRadius=0) circles = np.uint16(np.around(circles)) for i in circles[0,:]: # draw the outer circle cv2.circle(cimg,(i[0],i[1]),i[2],(255,0,0),3) # draw the center of the circle cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3) titles = ['Original Image', 'Adaptive Thresholding', "Canny", "Hough Circle"] images = [img, thresh, canny, cimg] for i in xrange(4): plt.subplot(2,2,i+1),plt.imshow(images[i],'gray') plt.title(titles[i]) plt.xticks([]),plt.yticks([]) plt.show()
Let us know if this is not enough.