pythonopencvarea

OpenCV: understanding the filterByArea parameter used in SimpleBlobDetector


I am trying to detect a large stain using OpenCV's SimpleBlobDetector following this SO answer.

Here is the input image:

enter image description here

I first tried working with params.filterByArea = False, which allowed to detect the large black stain:

enter image description here

However, smaller spots also ended up being detected. I therefore toggled params.filterByArea = True hoping to enforce a criterion on object area.

However, when setting params.filterByArea = True with params.minArea = 10 the largest stain is no longer identified:

enter image description here

I tried using other minArea parameters to no avail, even trying a minArea of 0, which should be equivalent to no filtering at all.

What am I missing here?


Solution

  • opencv maxArea param has 5000 as default value. Increasing it could detect blobs bigger than that

    import cv2
    import numpy as np
    
    def show_keypoints(im, keypoints):
        im_key = cv2.drawKeypoints(im, keypoints, np.array([]), (0, 0, 255), cv2.DRAW_MATCHES_FLAGS_DRAW_RICH_KEYPOINTS)
        cv2.imshow("Keypoints", im_key)
        cv2.waitKey(0)
    
    im_path = "test.png"
    im_m = cv2.imread(im_path, cv2.IMREAD_GRAYSCALE)
    params = cv2.SimpleBlobDetector_Params()
    
    
    params.filterByArea = True
    params.minArea = 10000
    params.maxArea = 50000
    
    detector = cv2.SimpleBlobDetector_create(params)
    keypoints = detector.detect(im_m)
    
    show_keypoints(im_m, keypoints)
    

    To print all detector params with default values use

    # a map suitable to get configuration from a yaml file
    param_map = {"blobColor":  "blob_color",
                "filterByArea":  "filter_by_area",
                "filterByCircularity":  "filter_by_circularity",
                "filterByColor":  "filter_by_color",
                "filterByConvexity":  "filter_by_convexity",
                "filterByInertia":  "filter_by_inertia",
                "maxArea":  "max_area",
                "maxCircularity":  "max_circularity",
                "maxConvexity":  "max_convexity",
                "maxInertiaRatio":  "max_inertia_ratio",
                "maxThreshold":  "max_threshold",
                "minArea":  "min_area",
                "minCircularity":  "min_circularity",
                "minConvexity":  "min_convexity",
                "minDistBetweenBlobs":  "min_dist_between_blobs",
                "minInertiaRatio":  "min_inertia_ratio",
                "minRepeatability":  "min_repeatability",
                "minThreshold":  "min_threshold",
                "thresholdStep":  "threshold_step"}
    for k in param_map:
        print(f"{k:<21}: {params.__getattribute__(k)}")
    

    result

    blobColor            : 0
    filterByArea         : True
    filterByCircularity  : False
    filterByColor        : True
    filterByConvexity    : False
    filterByInertia      : False
    maxArea              : 7000.0
    maxCircularity       : 3.4028234663852886e+38
    maxConvexity         : 3.4028234663852886e+38
    maxInertiaRatio      : 3.4028234663852886e+38
    maxThreshold         : 220.0
    minArea              : 500.0
    minCircularity       : 0.5
    minConvexity         : 0.20000000298023224
    minDistBetweenBlobs  : 10.0
    minInertiaRatio      : 0.10000000149011612
    minRepeatability     : 2
    minThreshold         : 50.0
    thresholdStep        : 10.0