FanClub
FanClub

Reputation: 31

Incomplete Circle detection with opencv python

is it possible to get the coordinates of the incomplete circle? i am using opencv and python. so i can find the most of the circles. But i have no clue how can i detect the incomplete cirlce in the picture. I am looking for a simple way to solve it.

captcha

import sys
import cv2 as cv
import numpy as np

## [load]
default_file = 'captcha2.png'
# Loads an image
src = cv.imread(cv.samples.findFile(default_file), cv.IMREAD_COLOR)
## [convert_to_gray]
# Convert it to gray
gray = cv.cvtColor(src, cv.COLOR_BGR2GRAY)
## [convert_to_gray]

## [reduce_noise]
# Reduce the noise to avoid false circle detection
gray = cv.medianBlur(gray, 3)
## [reduce_noise]

## [houghcircles]
#rows = gray.shape[0]
circles = cv.HoughCircles(gray, cv.HOUGH_GRADIENT, 1, 5,
                          param1=1, param2=35,
                          minRadius=1, maxRadius=30)
## [houghcircles]

## [draw]
if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0, :]:
        center = (i[0], i[1])
        # circle center
        cv.circle(src, center, 1, (0, 100, 100), 3)
        # circle outline
        radius = i[2]
        cv.circle(src, center, radius, (255, 0, 255), 3)
## [draw]

## [display]
cv.imshow("detected circles", src)
cv.waitKey(0)
## [display]

Hi - there is an other Picture. I want the x and y cords of the incomplete circle, light blue on the lower left.

enter image description here

Here the original Pic:

enter image description here

Upvotes: 2

Views: 2457

Answers (1)

Ahx
Ahx

Reputation: 7985

You need to remove the colorful background of your image and display only circles.

One approach is:


Binary mask:

enter image description here

Using the binary mask, we will detect the circles:

enter image description here

Code:


# Load the libraries
import cv2
import numpy as np

# Load the image
img = cv2.imread("r5lcN.png")

# Copy the input image
out = img.copy()

# Convert to the HSV color space
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

# Get binary mask
msk = cv2.inRange(hsv, np.array([0, 0, 130]), np.array([179, 255, 255]))

# Detect circles in the image
crc = cv2.HoughCircles(msk, cv2.HOUGH_GRADIENT, 1, 10, param1=50, param2=25, minRadius=0, maxRadius=0)

# Ensure circles were found
if crc is not None:

    # Convert the coordinates and radius of the circles to integers
    crc = np.round(crc[0, :]).astype("int")

    # For each (x, y) coordinates and radius of the circles
    for (x, y, r) in crc:

        # Draw the circle
        cv2.circle(out, (x, y), r, (0, 255, 0), 4)

        # Print coordinates
        print("x:{}, y:{}".format(x, y))

    # Display
    cv2.imshow("out", np.hstack([img, out]))
    cv2.waitKey(0)

Output:

x:178, y:60
x:128, y:22
x:248, y:20
x:378, y:52
x:280, y:60
x:294, y:46
x:250, y:44
x:150, y:62

Explanation

We have three chance for finding the thresholding:

    1. Simple Threshold result:
    • enter image description here
    1. Adaptive Threshold
    • enter image description here
    1. Binary mask
    • enter image description here

As we can see the third option gave us a suitable result. Of course, you could get the desired result with other options, but it might take a long time for finding the suitable parameters. Then we applied Hough circles, played with parameter values, and got the desired result.

Update

For the second uploaded image, you can detect the semi-circle by reducing the first and second parameters of the Hough circle.

crc = cv2.HoughCircles(msk, cv2.HOUGH_GRADIENT, 1, 10, param1=10, param2=15, minRadius=0, maxRadius=0)

Replacing the above line in the main code will result in:

enter image description here

Console result

x:238, y:38
x:56, y:30
x:44, y:62
x:208, y:26

Upvotes: 1

Related Questions