2

I’m trying to make Hough Transform find a circle faster or find another function that can do it faster.
(i do not need to stick to open cv, but it needs to be opensource)
I need to get centerpoint and radius.

My use case:
I have a square picture in grayscale, 4 aruco markers in the corners(detected earlier),
and a black circle approximately in the middle.
Rest of the picture is quite uniformly white-isch/gray.
Picture size is 1600x1600.
I know the approximate center position and radius of the circle

I use:

cv2.HoughCircles(image, cv2.HOUGH_GRADIENT, 1, 100, 100, 30, 200,250)

This takes about 35-40ms. I would love to get it down to about 15ms

I tried reducing resolution by half, but id does not give me very big benefit and makes result a bit "jittery".

Image i try to recognize: Image i try to recognize

BigFoot
  • 23
  • 4
  • If you know a starting point that is going to be within the circle, you could spiral your way out until you find all the edges. – Tim Roberts Nov 14 '22 at 21:52
  • The problem with the HoughCircles function is that it is very sensitive to noise. You can try to reduce it by applying a median filter before the HoughCircles function. You can also try to play with the parameters of the HoughCircles function. For example, try to increase the threshold and decrease the minimum distance between the centers of the detected circles. – Madison Courto Nov 14 '22 at 22:06
  • You could try to reduce the image size or detect in a subimage if you know roughly where to search. You could also use minEnclosingCircle if you know the relevant pixels or use a RANSAC circle detection similar to https://stackoverflow.com/a/20734263/2393191 but probably it will be slow when implemented in python. Not sure whether ED has a circle detection for python. – Micka Nov 14 '22 at 22:12
  • 1
    Please share a representative image if you would like some assistance. Thank you. – Mark Setchell Nov 14 '22 at 23:11
  • I added image to the original post – BigFoot Nov 15 '22 at 09:31
  • Threshold to black and white then run `np.sum()` with `axis=0` and `axis=1` – Mark Setchell Nov 15 '22 at 11:30
  • Then take row and column with smallest sum as centre. Or take mid-point between circle edges. – Mark Setchell Nov 15 '22 at 12:02
  • 1
    @MarkSetchell Thaks, that is a good idea and I think it will be fast. will try it tommorow. – BigFoot Nov 15 '22 at 21:09

1 Answers1

1

I didn't have much success with the method I suggested in the comments so I tried a different approach:

#!/usr/bin/env python3

import cv2

# Load image in greyscale
im = cv2.imread('J65Xt.jpg', cv2.IMREAD_GRAYSCALE)

# Define region of interest to exclude corner markers and reduce processing time
ROI = im[400:-400,400:-400]

# Threshold and invert
_, thr = cv2.threshold(ROI, 80,255,type=cv2.THRESH_BINARY_INV)

# Find contours
contours, _ = cv2.findContours(thr, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

# Get centroid from moments - may not really need this - could get from bounding box
M = cv2.moments(contours[0])
cX = int(M["m10"] / M["m00"])
cY = int(M["m01"] / M["m00"])
print(f'Centroid: cX={cX}, cY={cY} do not forget 400 offset of ROI')
# Mark centre in black
thr[cY-3:cY+3, cX-3:cX+3] = 0

# Get bounding box and draw it on
x, y, w, h = cv2.boundingRect(contours[0])
print(f'x={x}, y={y}, w={w}, h={h}')
print(f'cX={x+w/2}, cY={y+h/2}')
cv2.rectangle(thr, (x, y), (x + w, y + h), 255, 1)
cv2.imwrite('result.png', thr)

enter image description here

Output

Centroid: cX=432, cY=394 do not forget 400 offset of ROI
cX=432.5, cY=395.0

It takes 127 microseconds on my Mac if you exclude loading the input image and saving the output image.

Mark Setchell
  • 191,897
  • 31
  • 273
  • 432
  • Oh thank you! This drops my whole frame processing to 11ms, and it satisfies me a lot :) Now I need only to speed up getting frames from the camera but there are plenty of tutorials about it. Your "default" setting has a problem when the image is a bit blurry, but I think I can manage to fix this. – BigFoot Nov 18 '22 at 12:39