pythonopencvgeometrydetectionshapes

Detect circles in openCV


I have a problem with choosing right parameters for HoughCircles function. I try to detect circles from video. This circles are made by me, and has almost the same dimension. Problem is that camera is in move.

When I change maxRadius it still detect bigger circles somehow (see the right picture). I also tried to change param1, param2 but still no success. Left-original picture, Right - after blur and detected circles

gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
  blurred = cv2.medianBlur(gray, 25)#cv2.bilateralFilter(gray,10,50,50)


  minDist = 100
  param1 = 500
  param2 = 200#smaller value-> more false circles
  minRadius = 5
  maxRadius = 10
  circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, minDist, param1, param2, minRadius, maxRadius)

  if circles is not None:
    circles = np.uint16(np.around(circles))
    for i in circles[0,:]:
        cv2.circle(blurred,(i[0], i[1]), i[2], (0, 255, 0), 2) 

Maybe Im using wrong function?


Solution

  • The main problem in your code is 5th argument to HoughCircles function.

    According to documentation the argument list is:

    cv2.HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) → circles

    That means the 5th argument applies circles (it gives an option getting the output by reference, instead of using the returned value).

    Because you are not passing circles argument, you must pass named arguments for all arguments after the 4th argument (like param1=param1, param2=param2....).

    Parameter tuning issues:

    Here is the code:

    import numpy as np
    import cv2
    
    img = cv2.imread('circles.png')
    
    gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
    
    blurred = cv2.medianBlur(gray, 25) #cv2.bilateralFilter(gray,10,50,50)
    
    minDist = 100
    param1 = 30 #500
    param2 = 50 #200 #smaller value-> more false circles
    minRadius = 5
    maxRadius = 100 #10
    
    # docstring of HoughCircles: HoughCircles(image, method, dp, minDist[, circles[, param1[, param2[, minRadius[, maxRadius]]]]]) -> circles
    circles = cv2.HoughCircles(blurred, cv2.HOUGH_GRADIENT, 1, minDist, param1=param1, param2=param2, minRadius=minRadius, maxRadius=maxRadius)
    
    if circles is not None:
        circles = np.uint16(np.around(circles))
        for i in circles[0,:]:
            cv2.circle(img, (i[0], i[1]), i[2], (0, 255, 0), 2)
    
    # Show result for testing:
    cv2.imshow('img', img)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    Result:

    enter image description here