python get pixel positions from png

Viewed 1220

I'm working on a webapp that edits an image and part of it includes from a canvas on html I get a selection area which I save as a png example image below

enter image description here

next step is to get the x,y positions of the selection area so I know where only to apply an effect the code looks like this

pixels = img.load()
if cropped:
    x, y = position['left'], position['top']
else:
    x, y = 0, 0

img_width, img_height = 0, 0
matches = []
counter = 0
for _ in range(img.width * img.height):
    if img_width == img.width:
        img_width = 0
        img_height += 1

    counter += 1

    pixel = pixels[img_width, img_height]

    if pixel != (0, 0, 0, 0):
        matches.append([img_width+y, img_height+x])

    img_width += 1

if matches:
    filename = random_filename(extension='.pickle')
    with open(filename, 'wb') as f:
        # Pickle the 'data' dictionary using the highest protocol available.
        pickle.dump(matches, f, pickle.HIGHEST_PROTOCOL)

this gets the cells and saves it into a pickle.

However when I apply an effect to these cells there's a "halo effect" where a line of selection is a distance away from the main selection area

enter image description here

I made sure it wasn't the apply effect that had an issue, since it only uses the specified area it can't be.

I also went a step further and used one of the selection area pixels to reconstruct a png file to see if it has the issue (which it should)

In [1]: from PIL import Image

In [14]: new = Image.new('RGB', (600, 399))

In [15]: import pickle

In [16]: pickle_file = open('pickle_cells/qPxsEaw7wcQR5YWK9iZrb6r.pickle', 'rb')

In [17]: cells = pickle.load(pickle_file)

In [18]: pickle_file.close()

In [20]: cells[0]
Out[20]: [259, 117]

In [22]: for cell in cells:
    ...:     new.putpixel([cell[0], cell[1]], (50, 50, 50))
    ...:

In [23]: new.save('test.png')

In [24]:

this creates this image which shows the same error

enter image description here

2 Answers

I think the problem is that your PNG file does not contain what you expect. It has 41 unique colours in it - not the two you might expect.

Every single pixel is black in the file, and the background is white. Look at the red outlined parts in this analysis:

enter image description here

The 41 various shades of black are represented purely by variations in the alpha channel. Look at this histogram of the colours present, R=0, G=0, B=0 for all of them but the alpha channel varies a lot.

enter image description here

I would suggest thresholding the alpha channel.


I generated the above analysis with ImageMagick - included in most Linux distros and available for macOS and Windows. Just at the command-line:

magick identify -verbose image.png

Or, if using v6 or older, drop the magick and run:

identify -verbose image.png

Funny thing; this was caused by using antialiasing

img = img2.resize((full_width, full_height), PILImage.ANTIALIAS)

that was what was causing the issue.

Related