1

I have this kind of white and black images and i would like to save each white shape to an image that fits the shape's size.

I'm using connectedComponentsWithStats() in order to label connected regions, and then I use a rectangle englobing the region to extract it and saving it apart.

img = imread('shapes.png', IMREAD_GRAYSCALE)
_ , img = threshold(img,120,255,THRESH_BINARY)
n_labals, labels, stats, centroids = connectedComponentsWithStats(img)
for label in range(1,n_labals):
    width = stats[label, CC_STAT_WIDTH]
    height = stats[label, CC_STAT_HEIGHT]
    x = stats[label, CC_STAT_LEFT]
    y = stats[label, CC_STAT_TOP]
    roi = img[y-5:y + height+5, x-5:x + width+5]
    pyplot.imshow(roi,cmap='gray')
    pyplot.show()

However, this way I'm having some intersections between shapes as shown here

I would like to have each connected region saved into a separated image without any intersection as shown here


UPDATE

I took a rectangle engobing the interest region and then I ommoted the other labels

img = imread('shapes.png', IMREAD_GRAYSCALE)
_ , img = threshold(img,120,255,THRESH_BINARY)
n_labals, labels, stats, centroids = connectedComponentsWithStats(img)
for label in range(1,n_labals):
    width = stats[label, CC_STAT_WIDTH]
    height = stats[label, CC_STAT_HEIGHT]
    x = stats[label, CC_STAT_LEFT]
    y = stats[label, CC_STAT_TOP]
    roi = labels[y-1:y + height+1, x-1:x + width+1].copy() # create a copy of the interest region from the labeled image
    roi[ roi != label] = 0  # set the other labels to 0 to eliminate untersections with other labels
    roi[ roi == label] = 255 # set the interest region to white
    pyplot.imshow(roi,cmap='gray')
    pyplot.show()
neferjina
  • 31
  • 1
  • 6

1 Answers1

1

From the accepted answer of this post detailing the function connectedComponentsWithStats:

Labels is a matrix the size of the input image where each element has a value equal to its label.

So, this means that all pixels of object 1 have value 1, all pixels of object 2 have value 2, and so on.

My recommendation to deal with your problem is regionprops This is implemented in skimage (which is great for image processing in python)

You can install it using pip or conda, as detailed here

So, calling regionprops on an array of integer numbers will return a list of generators, which compute pretty much all basic object properties you can wish for. Specifically, the images you want to create can be accessed via 'filled_image':

import numpy as np
from skimage.measure import regionprops

# generate dummy image:
labels = np.zeros((100,100), dtype=np.int) # this does not work on floats
# adding two rectangles, similar to output of your label function
labels[10:20, 10:20] = 1
labels[40:50, 40:60] = 2

props = regionprops(labels)
print(type(props))

Now, we can go through each item in the list:

for prop in props:
   print(prop['label']) # individual properties can be accessed via square brackets
   cropped_shape = prop['filled_image'] # this gives you the content of the bounding box as an array of bool.
   cropped_shape = 1 * cropped_shape # convert to integer
   # save image with your favourite imsave. Data conversion might be neccessary if you use cv2
warped
  • 8,947
  • 3
  • 22
  • 49