def Circle_HT(input_image, d_range, smoothing): """ Circle Hough Transform :param d_range: range of diameters :param smoothing: remove noise :return: coordinate of circles, accumulation matrix """ # Generate probe circle points = [] for r in range(int(d_range[0] / 2), int(d_range[1] / 2 + 1)): # use value of radius for t in range(steps): theta = 2 * pi * t / steps points.append((r, int(r * cos(theta)), int(r * sin(theta)))) # accumulation matrix acc = defaultdict(int) for x, y in canny_edge_detector(input_image, smoothing=smoothing): for r, dx, dy in points: a = x - dx b = y - dy acc[(a, b, r)] += 1 # Filter circle by threshold circles = [] for k, v in sorted(acc.items(), key=lambda i: -i[1]): x, y, r = k # (x,y) is coordinate, v is frequency if v / steps >= threshold and all((x - xc) ** 2 + (y - yc) ** 2 > rc ** 2 for xc, yc, rc in circles): # Select the circles with higher frequency and not included by other circles circles.append((x, y, r)) return circles, acc
def detect_circles(input_file, output_file): # Load image: input_image_bad = Image.open(input_file) input_image = Image.new("RGB", input_image_bad.size) input_image.paste(input_image_bad) # Output image: output_image = Image.new("RGB", input_image.size) output_image.paste(input_image) draw_result = ImageDraw.Draw(output_image) # Find circles rmin = 18 rmax = 20 steps = 100 threshold = 0.4 points = [] for r in range(rmin, rmax + 1): for t in range(steps): points.append((r, int(r * cos(2 * pi * t / steps)), int(r * sin(2 * pi * t / steps)))) acc = defaultdict(int) for x, y in canny_edge_detector(input_image): for r, dx, dy in points: a = x - dx b = y - dy acc[(a, b, r)] += 1 circles = [] for k, v in sorted(acc.items(), key=lambda i: -i[1]): x, y, r = k if v / steps >= threshold and all((x - xc) ** 2 + (y - yc) ** 2 > rc ** 2 for xc, yc, rc in circles): #print(v / steps, x, y, r) circles.append((x, y, r)) for x, y, r in circles: draw_result.ellipse((x-r, y-r, x+r, y+r), outline=(255,0,0,0)) # Save output image output_image.save(output_file) return circles
draw_result = ImageDraw.Draw(output_image) # Find circles rmin = 55 rmax = 65 steps = 100 threshold = 0.235 points = [] for r in np.arange(rmin, rmax + 1, 1): for t in np.arange(0, steps, 1): points.append((r, int(r * cos(2 * pi * t / steps)), int(r * sin(2 * pi * t / steps)))) acc = defaultdict(int) for x, y in canny_edge_detector(input_image): for r, dx, dy in points: a = x - dx b = y - dy acc[(a, b, r)] += 1 circles = [] for k, v in sorted(acc.items(), key=lambda i: -i[1]): x, y, r = k if v / steps >= threshold and all( (x - xc)**2 + (y - yc)**2 > rc**2 for xc, yc, rc in circles): print(v / steps, x, y, r) circles.append((x, y, r)) for x, y, r in circles: draw_result.ellipse((x - r, y - r, x + r, y + r), outline=(255, 0, 0, 0))
# Find circles rmin = 10 # 18 rmax = 30 # 20 steps = 50 threshold = 0.4 points = [] for r in range(rmin, rmax + 1): for t in range(steps): points.append((r, int(r * cos(2 * pi * t / steps)), int(r * sin(2 * pi * t / steps)))) print('points', len(points)) acc = defaultdict(int) lst = canny_edge_detector(input_image) print('lst', len(lst)) for x, y in lst: for r, dx, dy in points: a = x - dx b = y - dy acc[(a, b, r)] += 1 print('f', len(acc)) circles = [] for k, v in sorted(acc.items(), key=lambda i: -i[1]): x, y, r = k if v / steps >= threshold and all( (x - xc)**2 + (y - yc)**2 > rc**2 for xc, yc, rc in circles): print(v / steps, x, y, r) circles.append((x, y, r))