2

I have a picture with random circles shown of which one circle is always open. The size, position and color of the circles are different each time but the background is always white.

I want to find the coordinates of the circle which is open programmatically. Here is a sample picture:

Sample picture

This picture roughly has coordinates of x:285 y:70. Here is my attempt:

import numpy as np
import argparse
import cv2

ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())

image = cv2.imread(args["image"])
black = cv2.imread('black.png')
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

ret,thresh = cv2.threshold(gray,127,255,0)
contours, hierarchy = cv2.findContours(thresh,cv2.RETR_TREE,cv2.CHAIN_APPROX_SIMPLE)
cv2.drawContours(black,contours,-1,(250,250,250),2)

newblack = cv2.cvtColor(black, cv2.COLOR_BGR2GRAY)

circles = cv2.HoughCircles(newblack, cv2.cv.CV_HOUGH_GRADIENT, 1, 1,
              param1=42,
              param2=35,
              minRadius=15,
              maxRadius=50)

if circles is not None:
        circles = np.round(circles[0, :]).astype("int")

        for (x, y, r) in circles:
                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)

        cv2.imshow("output", np.hstack([image, output]))
        print circles
        cv2.waitKey(0)

Almost finished!

The param2 Value determines which circle is found. I tweaked my code so it iterates over param2 values starting with a rather high value of 120.

When it finds a circle it stops.

# import the necessary packages
import numpy as np
import argparse
import cv2
import sys

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())

# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(args["image"])
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

str = 120

def findcircle( str ):
    circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1, 1,
    param1=42,
    param2=str,
    minRadius=10,
    maxRadius=100)

    if circles is not None:
        circles = np.round(circles[0, :]).astype("int")
        print circles
        sys.exit()

    while circles is None:
        str = str-1
        findcircle(str)

findcircle(str)

The success rate is around 80-100%

How do change the output of the variable "circles" to only show one circle incase more then 1 is found and how do I remove unwanted spaces and brackets?

Mike Laren
  • 8,028
  • 17
  • 51
  • 70
Ozanito
  • 43
  • 7
  • Would you let us know what you have done so far to look into this? What does the docs of OpenCV have to offer? – halfer Jul 11 '15 at 12:28
  • Tried cv2.findContours and cv2.HoughCircles and a combination of both so far with no luck. There must be an easier way to find an open/partial circle? – Ozanito Jul 11 '15 at 12:32
  • Thats what i have done so far. – Ozanito Jul 11 '15 at 13:36
  • Does your HoughCircle detect all closed- and open-circles? – Micka Jul 11 '15 at 14:32
  • depening on the parameters it detects all or some or none, yes. – Ozanito Jul 11 '15 at 14:44
  • Alright, thanks for posting your code - a much better question. The original (without an attempt) probably would have been put on hold. However, if you are now changing the topic of the question (something I do not normally advocate) then change all of it, rather than noting the new question at the bottom. – halfer Jul 11 '15 at 17:48
  • if you can understand how it works you can use parts of my solution in http://stackoverflow.com/questions/20698613/detect-semi-circle-in-opencv/20706100#20706100 to test each of your detected circles for closedness. – Micka Jul 11 '15 at 20:07
  • you dont happen to have the part that computes semi circles in python do you? – Ozanito Jul 13 '15 at 07:42

1 Answers1

0
# import the necessary packages
import numpy as np
import argparse
import cv2
import sys

# construct the argument parser and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required = True, help = "Path to the image")
args = vars(ap.parse_args())

# load the image, clone it for output, and then convert it to grayscale
image = cv2.imread(args["image"])
output = image.copy()
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

str = 120

def findcircle( str ):
    circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1, 1,
    param1=42,
    param2=str,
    minRadius=10,
    maxRadius=100)

    if circles is not None:
        circles = np.round(circles[0, :]).astype("int")
        index = [2]
        new_circles = np.delete(circles[0], index)
        print new_circles
        sys.exit()

    while circles is None:
        str = str-1
        findcircle(str)

findcircle(str)
Ozanito
  • 43
  • 7
  • Thanks for wanting to provide an answer. I've rolled back the question edit, as we do not mark questions as solved in the question, and the deletion seemed to remove a lot of the question's original context. Would you explain in the body of the answer how it solves the problem? It's fine to edit the question some more, but try to make it so the question matches this answer as if you asked them one after the other. This makes it better for future readers. Thanks! – halfer Jul 12 '15 at 00:12