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.
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:
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.