Search code examples
pythonimage-processingscikit-image

Cutting a patch around a segment of a segmented image


I have an segmented image into superpixels as follows:

from skimage.data import astronaut
img = astronaut()
segments_slic = slic(img, n_segments=250, compactness=10, sigma=1,
                     start_label=1)

fig = plt.figure(figsize = (16,8));
plt.imshow(mark_boundaries(img, segments_slic))

And got the following image:

enter image description here

I wish to cut a patch around each superpixel. Consider, for example, the patch around the shining part of the helmet colored red:

enter image description here

If I want to take a close (manual) look at the segments using plt.imshow(segments_slic[425:459,346:371]), I get this patch around the segment:

enter image description here

The pixels with the specific superpixel labe streach on row 425:459 and on columns 346:371.

Currently, I am doing this: patches = list()

for superpixel in np.unique(segments_slic ):
  x_min = np.min(np.where(segments == 15)[0]);
  x_max = np.max(np.where(segments == 15)[0]);
  y_min = np.min(np.where(segments == 15)[1]);
  y_max = np.max(np.where(segments == 15)[1]);
  patches.append(I[x_min:x_max,y_min:y_max,:]);

Not sure if it is correct, though it seems to be fine. What is the best way to generate such a patch for each superpixel? Moreover, is it possible to set the pixels in the patch, which do not belong to the superpixel, to black?


Solution

  • You can use regionprops and access the patch coordinates via region.bbox as in

    from skimage.data import astronaut
    import matplotlib.pyplot as plt
    from skimage.segmentation import slic
    from skimage.segmentation import mark_boundaries
    from skimage.measure import regionprops
    import matplotlib.patches as mpatches
    
    img = astronaut()
    segments_slic = slic(img, n_segments=250, compactness=10, sigma=1, start_label=1)
    
    fig, ax = plt.subplots(figsize=(16, 8))
    ax.imshow(img)
    
    for region in regionprops(segments_slic):
        # draw rectangle around segmented coins
        minr, minc, maxr, maxc = region.bbox
        rect = mpatches.Rectangle((minc, minr), maxc - minc, maxr - minr,
                                  fill=False, edgecolor='red', linewidth=2)
        ax.add_patch(rect)
        # access patch via img[minr:maxr, minc:maxc]
    
    plt.imshow(mark_boundaries(img, segments_slic))
    plt.show()
    

    This results in patches around superpixels

    Example adapted from here.

    EDIT: Furthermore, with region.image you get a mask of your region to set the others to black.