Search code examples
pythonimage-processingpython-imaging-librarypng

Is there any way to only extract "corner" vertex points from a PNG?


I'm currently experimenting with the idea of extracting data points from a specific PNG file. For reference, the PNG file looks like this : Picture of PNG

The current code I'm using to extract the data looks like this, I'm using the Python image library to identify points of the image :

def imageProcess(filename) :
    #Declaring data object
    data = []
    #Loading image for modification
    with Image.open(filename) as im:
        px = im.load()
        #Grabbing values
        width,height = im.size
        print(width , height)

        #For loop
        for x in range(width) :
            for y in range(height) :
                #Removes white space from the image
                if px[x,y] != (255,255,255,0) :
                    data.append({"x" : x*5, "y" : y*5,"color" :  px [ x , y ]})

        print(type(data))

        return data

Whilst this code does work fine, I'm trying to discard the data points that represent a line in the PNG file, I only want the corners to be specific. To give a better idea of what I want :

Instead of :

{'x': 518, 'y': 741, 'color': (226, 226, 226, 17)}
# All of the data below is a waste, I don't need it
{'x': 518, 'y': 742, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 743, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 744, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 745, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 746, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 747, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 748, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 749, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 750, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 751, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 752, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 753, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 754, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 755, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 756, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 757, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 758, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 759, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 760, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 761, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 762, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 763, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 764, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 765, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 766, 'color': (226, 226, 226, 17)}
# The point below represents the corner
{'x': 518, 'y': 767, 'color': (244, 244, 244, 2)} 

I only want the first and last value since it represents the corners :

#This is what I want to achieve
{'x': 518, 'y': 741, 'color': (226, 226, 226, 17)}
{'x': 518, 'y': 767, 'color': (244, 244, 244, 2)} 

I'm welcome to using different python libraries apart from PIL if needed to solve this problem. Thank you very much.

Edit : Here is a (sorry for the low res) picture explaining what data points I need to get and all of the data points need to be discarded. I've put red dots identifying what points I need to get. Thanks.


Solution

  • Sorry, I don't have the time to write up a proper Python answer like I normally would, but it seems cruel not to show you how you might do it. I used "Hit and Miss Morphology" which you can find in OpenCV, scikt-image and wand. I used ImageMagick in the Terminal to generate this:

    enter image description here

    Here is the command and it would be pretty similar in wand since that is a Python ImageMagick binding:

    magick plan.png -alpha off -threshold 99%  \
        \( +clone -define morphology:showkernel=1 -morphology HMT "3x3>: nan,0,0 0,nan,nan 0,nan,nan " -morphology Dilate Ring -background red -alpha shape  \) -composite result.png
    

    The crucial part in there is the "Hit and Miss" kernel, which is here:

    "3x3>: nan,0,0 0,nan,nan 0,nan,nan "
    

    That means I am looking for this 3x3 shape:

    ANY    BLACK  BLACK
    BLACK  ANY    ANY
    BLACK  ANY    ANY
    

    Hopefully you can see that is a horizontal and a vertical black line meeting in the top-left corner of the 3x3 shape where the actual corner is not necessarily black because those bits are missing in your diagram! You would use a 1 if you wanted to insist on a white pixel at some location in the 3x3 grid. You would use a larger grid if you waned to be even. ore sure you were dealing with a corner of a longer line.

    The > means that I want to find that corner at any of the 4 positions you would get if you rotated it 90, 180 and 270 degrees, so I am looking for top-left, top-right, bottom-right and bottom-left corners.

    You can see as much if I print the debug output corners showing the kernels:

    Kernel #0 "User Defined" of size 3x3+1+1 with values from 0 to 0
    Forming a output range from 0 to 0 (Zero-Summing)
     0:       nan         0         0
     1:         0       nan       nan
     2:         0       nan       nan
    Kernel #1 "User Defined@90" of size 3x3+1+1 with values from 0 to 0
    Forming a output range from 0 to 0 (Zero-Summing)
     0:         0         0       nan
     1:       nan       nan         0
     2:       nan       nan         0
    Kernel #2 "User Defined@180" of size 3x3+1+1 with values from 0 to 0
    Forming a output range from 0 to 0 (Zero-Summing)
     0:       nan       nan         0
     1:       nan       nan         0
     2:         0         0       nan
    Kernel #3 "User Defined@270" of size 3x3+1+1 with values from 0 to 0
    Forming a output range from 0 to 0 (Zero-Summing)
     0:         0       nan       nan
     1:         0       nan       nan
     2:       nan         0         0
    

    Note that the -morphology Dilate Ring -background red -alpha shape is just for drawing the red circles around the points so you can see them. You can omit this and you will just get the points on a blank canvas.

    If this method interests you, there is an excellent description by Anthony Thyssen here, but start at the top of the page if you are new to morphology.