Circular Hough Transform misses circles

前端 未结 1 1132
既然无缘
既然无缘 2020-12-10 08:52

I\'ve read a lot about the Circular Hough transform on Stack Overflow, but I seem to be missing something. I wrote a program that is supposed to detect the circles of a \"Bu

相关标签:
1条回答
  • 2020-12-10 09:28

    As I mentioned in my comment, you'll need to run successive iterations of cv2.HoughCircles for different range of radii to ensure that you get all of the circles. With the way the Circular Hough Transform works, specifying a minimum and maximum radius that has quite a large range will be inaccurate and will also be slow. They don't tell you this in the documentation, but for the Circular Hough Transform to work successfully, the following two things need to be valid:

    maxRadius < 3*minRadius
    maxRadius - minRadius < 100
    

    With the above, blindly making the minimum radius very small and the maximum radius very large won't give you great results. Therefore, what you could do is start at... say...radius=1, then iterate up to radius=300 in steps of 20. Between each chunk of 20, run cv2.HoughCircles and update your image with these contours.

    Doing this requires very little modification to your code. BTW, I removed the unsharp masking it because I was getting poor results with it. I also changed a couple of parameters in cv2.HoughCircles slightly to get this to work as best as possible given your situation:

    import cv2
    import cv2.cv as cv
    import numpy as np
    import math
    # Load Image
    img = cv2.imread('circles1.png',0)
    cimg = cv2.cvtColor(img,cv2.COLOR_GRAY2BGR)
    
    # Specify different radii
    radii = np.arange(0,310,10)
    
    # For each pair of radii...
    for idx in range(len(radii)-1):
        # Get the minimum and maximum radius
        # Note you need to add 1 to each minimum
        # as the maximum of the previous pair covers this new minimum
        minRadius = radii[idx]+1
        maxRadius = radii[idx+1]
    
        # Hough Transform - Change here
        circles = cv2.HoughCircles(img,cv.CV_HOUGH_GRADIENT,1,5,
                                   param1=25,param2=75,minRadius=minRadius,maxRadius=maxRadius)
    
        # Skip if no circles are detected - Change here
        if circles is None:
            continue
    
        circles = np.uint16(np.around(circles))
    
        # Go over circles, eliminating the ones that are not cocentric enough
        height, width = img.shape
        center = (width/2,height/2)
        for i in circles[0,:]:
            # draw the outer circle
            if math.sqrt((center[0]-i[0])**2 + (center[1]-i[1])**2) < 15:
                cv2.circle(cimg,(i[0],i[1]),i[2],(0,255,0),1)
                # draw the center of the circle
                cv2.circle(cimg,(i[0],i[1]),2,(0,0,255),3)
    
    cv2.imshow('detected circles',cimg)
    
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    I get this figure:

    Unfortunately it isn't perfect as it doesn't detect all of the circles. You'll have to play around with the cv2.HoughCircles function until you get good results.


    However, I wouldn't recommend using cv2.HoughCircles here. May I suggest using cv2.findContours instead? This finds all of the contours in the image. In this case, these will be the black circles. However, you need to reverse the image because cv2.findContours assumes non-zero pixels are object pixels, so we can subtract 255 from the image assuming a np.uint8 type:

    # Make copy of original image
    cimg2 = cv2.cvtColor(img, cv2.COLOR_GRAY2BGR)
    
    # Find contours
    contours,_ = cv2.findContours(255 - img, cv2.RETR_LIST, cv.CV_CHAIN_APPROX_NONE)
    
    # Draw all detected contours on image in green with a thickness of 1 pixel
    cv2.drawContours(cimg2, contours, -1, color=(0,255,0), thickness=1)
    
    # Show the image
    cv2.imshow('detected circles', cimg2)
    cv2.waitKey(0)
    cv2.destroyAllWindows()
    

    This is what I get:

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