Preview:
import cv2
import numpy as np

img = cv2.imread('blackdots.jpg')
gray_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)

ret, thresh = cv2.threshold(gray_img, 170, 255, cv2.THRESH_BINARY) # <--- Try different values here

accum_size = 1
# Minimum distance between the centers of the detected circles.
minDist = 30
#First method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the higher threshold of the two passed to the Canny() edge detector (the lower one is twice smaller).
param1 = 50
# Second method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first.
param2 = 5
#
minRadius = 1
#
maxRadius = 10
circles = cv2.HoughCircles(thresh, cv2.HOUGH_GRADIENT, accum_size, minDist,
                           param1=param1, param2=param2,
                           minRadius=minRadius, maxRadius=maxRadius)
circles = circles.reshape(1,circles.shape[1], circles.shape[2])
if circles is not None:
    circles = np.uint16(np.around(circles))
    for ind, i in enumerate(circles[0, :]):
        center = (i[0], i[1])
        radius = 15
        cv2.circle(img, center, radius, (255, 0, 255), 3)

thresh = cv2.resize(thresh, (1280, 720)) # <---- This is just for easier display
img = cv2.resize(img, (1280, 720)) # <---- This is just for easier display
cv2.imwrite('circles_black_dot.png', img)
cv2.imwrite('threshold_black_dots.png', thresh)
downloadDownload PNG downloadDownload JPEG downloadDownload SVG

Tip: You can change the style, width & colours of the snippet with the inspect tool before clicking Download!

Click to optimize width for Twitter