I would like to determine the center positions of the tips of the syringes in this (video still) image. The tips are nominally round and of known size and quantity.
I am currently putting red ink on the tips to make them easier to detect. It would be nice to not to have to do this but I think without it, detection would be very difficult. Anyone like a challenge?
I started off trying SimpleBlobDetector as it has some nice filtering. One thing I couldn't figure out was how to get SimpleBlobDetector to detect the hollow circles (rings)?
I then tried canny + hough but the circle detection was too unstable, the positions jumped around.
I am currently using findContours + minEnclosingCircle which works OK but still quite unstable. The mask looks like this. The result. You can see the accuracy is not great:
I briefly looked at RANSAC but I couldn't find a Python example that would detect multiple circles plus the edge detection is tricky.
My current code:
# https://stackoverflow.com/questions/32522989/opencv-better-detection-of-red-color
frame_inv = ~frame0
# Convert BGR to HSV
hsv = cv2.cvtColor(frame_inv, cv2.COLOR_BGR2HSV)
blur = cv2.GaussianBlur(hsv, (5, 5), 0)
# define range of color in HSV
lower_red = np.array([90 - 10, 70, 50])
upper_red = np.array([90 + 10, 255, 255])
# Threshold the HSV image to get only red colors
mask = cv2.inRange(hsv, lower_red, upper_red)
# cv2.imshow('Mask', mask)
kernel = np.ones((5, 5), np.uint8)
dilate = cv2.dilate(mask, kernel)
# cv2.imshow('Dilate', dilate)
contours = cv2.findContours(dilate, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)[0]
tipXY = []
for c in contours:
area = cv2.contourArea(c)
if area > 200:
(x, y), r = cv2.minEnclosingCircle(c)
center = (int(x), int(y))
r = int(r)
shift = 2
factor = 2 ** shift
cv2.circle(frame0, (int(round((x) * factor)), int(round((y) * factor))),
int(round(10 * factor)), (0, 255, 0), 2, shift=shift)
tipXY.append(center)
Any suggestions to improve the position detection accuracy/stability?