Skip to content
Advertisement

OpenCV – Detect points along a curve

I need to detect the points along these curves, in particular I need the position on the image of one of the two points starting from the left:

enter image description here

I tried to detect Hough Points like that:

import cv2
import numpy as np

# detect circles in the image
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
circles = cv2.HoughCircles(gray, cv2.HOUGH_GRADIENT, 1.2, 100)
# ensure at least some circles were found
if circles is not None:
    # convert the (x, y) coordinates and radius of the circles to integers
    circles = np.round(circles[0, :]).astype("int")
    # loop over the (x, y) coordinates and radius of the circles
    for (x, y, r) in circles:
        # draw the circle in the output image, then draw a rectangle
        # corresponding to the center of the circle
        cv2.circle(output, (x, y), r, (0, 255, 0), 4)
        cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
    # show the output image
    cv2.imshow("output", np.hstack([image, output]))
    cv2.waitKey(0)

But it doesn’t get the right points and I suppose that this is because the points are positioned along the two curves. Is there a way to detect points along a curve?

Advertisement

Answer

Just found the solution following the comment of @HansHirse. I followed these steps:

  1. Color threshold
  2. Erosion
  3. Finding contours

This is the code:

import cv2
import numpy as np

hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
mask = cv2.inRange(hsv_image, lowerb=(85, 0, 0), upperb=(95, 255, 255))

# Masking with green
imask = mask > 0
green = np.zeros_like(hsv_image, np.uint8)
green[imask] = hsv_image[imask]

kernel = np.ones((8, 8), np.uint8)
erosion = cv2.erode(green, kernel, iterations=1)

gray = cv2.cvtColor(erosion, cv2.COLOR_BGR2GRAY)
thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]

# Filter out large non-connecting objects
cnts = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
cnts = cnts[0] if len(cnts) == 2 else cnts[1]
for c in cnts:
    area = cv2.contourArea(c)
    if area < 500:
        cv2.drawContours(thresh,[c],0,0,-1)

# Morph open using elliptical shaped kernel
kernel = cv2.getStructuringElement(cv2.MORPH_ELLIPSE, (3,3))
opening = cv2.morphologyEx(thresh, cv2.MORPH_OPEN, kernel, iterations=3)

# Find circles
cnts = cv2.findContours(opening,  cv2.RETR_LIST,
                        cv2.CHAIN_APPROX_SIMPLE)[-2]
for c in cnts:
    area = cv2.contourArea(c)
    if area > 0 and area < 50:
        ((x, y), r) = cv2.minEnclosingCircle(c)
        cv2.circle(image, (int(x), int(y)), int(r), (36, 255, 12), 2)

cv2.imshow('image', image)
cv2.waitKey()

The result is the following image where the dots are represented by the green circles

enter image description here

User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement