6

I am using OpenCV in Python to be able to identify only the Leaf presented on the image. I already be able to segment my image, and now I am currently stuck at "how to crop the largest component after I have detected all of them. Below is the codes, please have a look.

  1. Using scipy.ndimage, I was unable to advance after find the components:

    def undesired_objects ( image ):
        components, n = ndimage.label( image )
        components = skimage.morphology.remove_small_objects( components, min_size = 50 )
        components, n = ndimage.label( components )
        plot.imshow( components )
        plot.show()
    
  2. Using OpenCV connectedComponentsWithStats:

    def undesired_objects ( image ):
        image = image.astype( 'uint8' )
        nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=4)
        sizes = stats[1:, -1]; nb_components = nb_components - 1
        min_size = 150
        img2 = np.zeros(( output.shape ))
        for i in range(0, nb_components):
            if sizes[i] >= min_size:
                img2[output == i + 1] = 255
                plot.imshow( img2 )
                plot.show()
    

However, in both approaches, I'm still getting more than one component as result. Below, you will find the binary image:

Binary Image

4
  • Can you upload the binary image of which you are trying to find the largest connected component ? Commented Nov 1, 2017 at 13:18
  • @ZdaR Updated with the binary image! Commented Nov 1, 2017 at 13:27
  • What's the problem with your result ? Your code is not guaranteed to output only one component. It will select all components bigger than your min_size parameter. And since you're not clearing your img2 between different components, they will all end up being drawn on the same image. Commented Nov 1, 2017 at 14:04
  • Yes, @Sunreef. I want to remove the min_size parameter to select only the bigger one; however, I'm stuck on it Commented Nov 1, 2017 at 14:23

2 Answers 2

8

I would replace your code with something like this:

def undesired_objects (image):
    image = image.astype('uint8')
    nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=4)
    sizes = stats[:, -1]

    max_label = 1
    max_size = sizes[1]
    for i in range(2, nb_components):
        if sizes[i] > max_size:
            max_label = i
            max_size = sizes[i]

    img2 = np.zeros(output.shape)
    img2[output == max_label] = 255
    cv2.imshow("Biggest component", img2)
    cv2.waitKey()

The loop on components now finds the component with the biggest area and displays it at the end of the loop.

Tell me if this works for you as I haven't tested it myself.

Sign up to request clarification or add additional context in comments.

1 Comment

Thank you, @Sunreef. It works well; however, my results are still poor, I will need to find another approach to solve my issue
2

Using cv2.CC_STAT_AREA for readability:

# Connected components with stats.
nb_components, output, stats, centroids = cv2.connectedComponentsWithStats(image, connectivity=4)

# Find the largest non background component.
# Note: range() starts from 1 since 0 is the background label.
max_label, max_size = max([(i, stats[i, cv2.CC_STAT_AREA]) for i in range(1, nb_components)], key=lambda x: x[1])

More here: https://stackoverflow.com/a/35854198/650885

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.