简体   繁体   中英

Find the maximum of R,G,B in a ndarray according to their group stored in a different ndarray

I'm currently working on image superpixel SLIC segmentation with the package skimage.segmentation .

My original image is 3042*4032 (12Mpx). In skimage , the array's shape is (3042,4023,3) . After the segmentation, I have around 3000 superpixels represented in a 3042*4032 array.

My goal is to find for each superpixel, the proportion of pixel which have their maximum value on the Red channel, the Blue channel and the Green channel .

I already have a function which give me the index of the maximum in the entire image:

def proportion_majoritaire_rgb_image(img):
    """ In a pixel, which channel [R,G,B] has the maximum value ?

    :param img: image (N,m) skimage rgb
    :return: (N,m) array with indexes [0,1,2]
    """

    return np.argmax(img, axis=2)

And by filtering the image on a single label, i can get the proportion of max RGB in a single label:

def proportion_majoritaire_rgb_label(img, matrice_label):
    """ 
    :param img: image (N,m) skimage rgb
    :param matrice_label: ndarray (N,m) labels SLIC
    :return: (K, 3) array of K labels and 3 proportions
    """

    indice_max_rgb = proportion_majoritaire_rgb_image(img)

    n_pixel_max_rgb = []

for k in np.unique(image_grains_ble_slic).flat:
    label_data = indice_max_rgb[matrice_label == k]
    n_pixel_max_rgb.append(np.unique(label_data, return_counts=True)[1] / np.shape(label_data)[0])

    return n_pixel_max_rgb

The issue is how to get this information for all my 3000 labels without this for loop? It takes too much time to compute, is there any other way?

The final output should be a ndarray (K,3) with K labels and for each channel RGB the proportion of pixels which have the maximum value.

Thanks in advance !

EDIT: Using np.unique(image_grains_ble_slic).flat as an iterator for the loop seems to be faster, but my goal of avoiding the for loop still stands

It's a little hacky because of a long-standing feature request for skimage.measure.regionprops to allow measuring multichannel images. But, we can hack it together with some repeated calls to regionprops_table , which gives us vectorised output:

from skimage import measure

index_max_rgb = np.argmax(image, axis=2)
max_index_images = [
    (index_max_rgb == i).astype(float) for i in range(3)
]
proportions_per_channel = [
    measure.regionprops_table(
        image_grains_ble_slic,
        intensity_image=intensity,
        properties=('mean_intensity',),
    )['mean_intensity']
    for intensity in max_index_images
]
proportions = np.stack(proportions, axis=1)

By the way, be sure that you use start_label=1 with SLIC because regionprops ignores the 0 label as belonging to the background.

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