HoughCircles circle detection using opencv and python-

后端 未结 2 1942
心在旅途
心在旅途 2021-02-01 09:47

I am trying to use OpenCV\'s (Hough)Circle detection to.. detect circles. I created a solid circle on a black background, tried to play with the parameters, used blur and everyt

相关标签:
2条回答
  • 2021-02-01 10:35

    Your code is working just fine. The problem is in your HoughCircles threshold parameters.

    Let's try to understand the parameters that you're using from OpenCV Docs:

    param1 – First method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the higher threshold of the two passed to the Canny() edge detector (the lower one is twice smaller).

    param2 – Second method-specific parameter. In case of CV_HOUGH_GRADIENT , it is the accumulator threshold for the circle centers at the detection stage. The smaller it is, the more false circles may be detected. Circles, corresponding to the larger accumulator values, will be returned first.

    So, as you can see, internally the HoughCircles function calls the Canny edge detector, this means that you can use a gray image in the function, instead of their contours.

    Now reduce the param1 to 30 and param2 to 15 and see the results in the code that follows:

    import cv2
    import numpy as np
    
    img = np.ones((200,250,3), dtype=np.uint8)
    for i in range(50, 80, 1):
        for j in range(40, 70, 1):
            img[i][j]*=200
    
    cv2.circle(img, (120,120), 20, (100,200,80), -1)
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    circles = cv2.HoughCircles(gray, cv2.cv.CV_HOUGH_GRADIENT, 1, 20,
                  param1=30,
                  param2=15,
                  minRadius=0,
                  maxRadius=0)
    
    print circles
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(img,(i[0],i[1]),i[2],(0,255,0),2)
        cv2.circle(img,(i[0],i[1]),2,(0,0,255),3)
    
    cv2.imshow('circles', img)
    
    k = cv2.waitKey(0)
    if k == 27:
        cv2.destroyAllWindows()
    

    HoughCircles

    0 讨论(0)
  • 2021-02-01 10:42

    If you're not getting HoughCircles to bring you pixel perfect solutions for obvious circles then you're not using it right

    Your mistake is you're trying to hand-tune your hyperparameters by yourself. That's not going to work. Have the computer auto-tune the parameters for you:

    import numpy as np
    import argparse
    import cv2
    import signal
    
    from functools import wraps
    import errno
    import os
    import copy
    
    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"])
    orig_image = np.copy(image)
    output = image.copy()
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
    
    cv2.imshow("gray", gray)
    cv2.waitKey(0)
    
    circles = None
    
    minimum_circle_size = 100      #this is the range of possible circle in pixels you want to find
    maximum_circle_size = 150     #maximum possible circle size you're willing to find in pixels
    
    guess_dp = 1.0
    
    number_of_circles_expected = 1          #we expect to find just one circle
    breakout = False
    
    max_guess_accumulator_array_threshold = 100     #minimum of 1, no maximum, (max 300?) the quantity of votes 
                                                    #needed to qualify for a circle to be found.
    circleLog = []
    
    guess_accumulator_array_threshold = max_guess_accumulator_array_threshold
    
    while guess_accumulator_array_threshold > 1 and breakout == False:
        #start out with smallest resolution possible, to find the most precise circle, then creep bigger if none found
        guess_dp = 1.0
        print("resetting guess_dp:" + str(guess_dp))
        while guess_dp < 9 and breakout == False:
            guess_radius = maximum_circle_size
            print("setting guess_radius: " + str(guess_radius))
            print(circles is None)
            while True:
    
                #HoughCircles algorithm isn't strong enough to stand on its own if you don't
                #know EXACTLY what radius the circle in the image is, (accurate to within 3 pixels) 
                #If you don't know radius, you need lots of guess and check and lots of post-processing 
                #verification.  Luckily HoughCircles is pretty quick so we can brute force.
    
                print("guessing radius: " + str(guess_radius) + 
                        " and dp: " + str(guess_dp) + " vote threshold: " + 
                        str(guess_accumulator_array_threshold))
    
                circles = cv2.HoughCircles(gray, 
                    cv2.cv.CV_HOUGH_GRADIENT, 
                    dp=guess_dp,               #resolution of accumulator array.
                    minDist=100,                #number of pixels center of circles should be from each other, hardcode
                    param1=50,
                    param2=guess_accumulator_array_threshold,
                    minRadius=(guess_radius-3),    #HoughCircles will look for circles at minimum this size
                    maxRadius=(guess_radius+3)     #HoughCircles will look for circles at maximum this size
                    )
    
                if circles is not None:
                    if len(circles[0]) == number_of_circles_expected:
                        print("len of circles: " + str(len(circles)))
                        circleLog.append(copy.copy(circles))
                        print("k1")
                    break
                    circles = None
                guess_radius -= 5 
                if guess_radius < 40:
                    break;
    
            guess_dp += 1.5
    
        guess_accumulator_array_threshold -= 2
    
    #Return the circleLog with the highest accumulator threshold
    
    # ensure at least some circles were found
    for cir in circleLog:
        # convert the (x, y) coordinates and radius of the circles to integers
        output = np.copy(orig_image)
    
        if (len(cir) > 1):
            print("FAIL before")
            exit()
    
        print(cir[0, :])
    
        cir = np.round(cir[0, :]).astype("int")
    
        for (x, y, r) in cir:
            cv2.circle(output, (x, y), r, (0, 0, 255), 2)
            cv2.rectangle(output, (x - 5, y - 5), (x + 5, y + 5), (0, 128, 255), -1)
    
        cv2.imshow("output", np.hstack([orig_image, output]))
        cv2.waitKey(0)
    

    The above code converts this:

    To this:

    For more information about what this is doing, see: https://stackoverflow.com/a/46500223/445131

    0 讨论(0)
提交回复
热议问题