pythonimage-processingimage-segmentationhorizontal-line

how to vertically segment an image?


I have images like this:

Input image

where all objects are connected through a horizontal line. all the symbols have different widths so can't extract all shapes using a fixed width or splitting points like when we split an array.

In this image, there are 4 symbols but in some other cases it can be more or less than 4 so here also I can't perform something like "4 symbols so divide the input image width vertically into 4 different widths. so I don't know how to extract whatever symbols the image might have efficiently like this output I want

the output I want .

Can you guys help me with this?

Image
to
output


Solution

  • import urllib.request
    from PIL import Image
    from scipy import signal
    import numpy as np
    from matplotlib import pyplot as plt
    
    urllib.request.urlretrieve(
      'https://i.sstatic.net/iMKIP.jpg',
       "img.png")
    img = Image.open("img.png")
    img.show()
    

    enter image description here

    arr = (np.array(img)<(255)/2) #I'm considering black parts as filled
    plt.imshow(arr)
    

    enter image description here

    plt.subplot(211)
    plt.imshow(arr, aspect="auto")
    plt.subplot(212)
    plt.plot(arr.sum(axis=0))
    plt.xlim(0,arr.shape[1])
    

    enter image description here

    Then, in order to find local min:

    x_lines = signal.find_peaks(-arr.sum(axis=0))[0]
    
    plt.imshow(arr, aspect="auto")
    plt.vlines(x_lines, 0, arr.shape[0], color="r")
    

    enter image description here

    Finally if we consider a threshold (for example 50 filled pixel in columns):

    threshold = 50
    
    x_lines = signal.find_peaks(-arr.sum(axis=0))[0]
    x_lines = x_lines[arr.sum(axis=0)[x_lines]<threshold]
    
    plt.imshow(arr, aspect="auto")
    plt.vlines(x_lines, 0, arr.shape[0], color="r")
    

    enter image description here

    Edit:

    To split picture you need

    for i, x in enumerate(x_lines):
        if i==0:
            plt.imshow(arr[:,:x_lines[i]], cmap="Greys")
            plt.savefig("fig%i"%i)
            plt.show()
        else:
            plt.imshow(arr[:,x_lines[i-1]:x_lines[i]], cmap="Greys")
            plt.savefig("fig%i"%i)
            plt.show()
            
    plt.imshow(arr[:,x_lines[i]:], cmap="Greys")
    plt.savefig("fig%i"%(i+1))
    plt.show()