简体   繁体   中英

Taking the largest component of connected components with OpenCV in python

I have some photos of leaves with alpha channel - the background alpha channel is 0, and the leaf pixels alpha channel in the photo is 255.

I want to separate the image to connected Components. and then take the large connected Component. in order to erase dirt like in the red mark. This is the image I'm talking about here: leaf image

And this is my current code:

def remove_pixels(image_path, img_file_output_path):
    img = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
    alpha = img[:, :, 3]
    alpha = cv2.threshold(alpha, 0, 255, cv2.THRESH_BINARY)[1]
    num_labels, labels_im = cv2.connectedComponents(alpha,connectivity=4)
    new_img = np.zeros(img.shape)
    largest_label = 1 + np.argmax(labels_im[1:, cv2.CC_STAT_AREA])  
    h, w = labels_im.shape
    for i in range(h*w):
        x = i // w
        y = i % w
        if labels_im[x,y] == largest_label:
            new_img[x,y] = img[x,y]
    cv2.imwrite(img_file_output_path, new_img)

It is not working, any help is really appreciated.
Thank you:)
-------------------------------------------------

This is my new code:

def remove_pixels(image_path, img_file_output_path):
    img = cv2.imread(image_path, cv2.IMREAD_UNCHANGED)
    alpha = img[:, :, 3]
    contours = cv2.findContours(alpha, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = contours[0] if len(contours) == 2 else contours[1]
    big_contour = max(contours, key=cv2.contourArea)

    # draw white filled contour on black background to use as new alpha channel
    new_alpha = np.zeros_like(alpha)
    new_alpha = cv2.drawContours(new_alpha, [big_contour], 0, 255, -1)

    # put new_alpha into alpha channel of img
    new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
    new_img[:, :, 3] = new_alpha

    cv2.imwrite(img_file_output_path, new_img)

and the picture: new picture

Here is one way in Python/OpenCV.

 - Read the input
 - Threshold on white and invert so that the leaf, etc is white on black background
 - Get the contours
 - Filter the contours on area to keep only the largest
 - Draw a white filled contour on a black background using the largest contour
 - Put that image into the alpha channel of the input
 - Save the result

Input:

在此处输入图像描述

import cv2
import numpy as np

# load image
img = cv2.imread('leaf3.jpg')

# threshold on white and invert
thresh = cv2.inRange(img, (220,220,220), (255,255,255))
thresh = 255 - thresh

# get the largest contour
contours = cv2.findContours(thresh, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
contours = contours[0] if len(contours) == 2 else contours[1]
big_contour = max(contours, key=cv2.contourArea)

# draw white filled contour on black background to use as new alpha channel
new_alpha = np.zeros_like(thresh)
new_alpha = cv2.drawContours(new_alpha, [big_contour], 0, 255, -1)

# put new_alpha into alpha channel of img 
new_img = cv2.cvtColor(img, cv2.COLOR_BGR2BGRA)
new_img[:, :, 3] = new_alpha

# save result
cv2.imwrite("leaf3_alpha_cleaned.png", new_img)

Result:

在此处输入图像描述

Optional - Make the background white in place of transparent.

# make background white
new_img2 = img.copy()
new_img2[new_alpha==0] = (255,255,255)
cv2.imwrite("leaf3_alpha_cleaned2.png", new_img2)

在此处输入图像描述

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM