Python Working with PNG images in Python

Click For Summary
To work with PNG images in Python, converting them to bitmap format simplifies pixel manipulation, as they can be treated as 2D arrays. The discussion highlights the need to extract RGB pixel data, isolate image sections, and output modified images based on algorithm results. Libraries such as PIL (Pillow), PyPNG, and OpenCV are recommended for these tasks, with Pillow being particularly noted for its ease of use in channel operations. Users are encouraged to explore documentation and examples to understand how to manipulate pixel data and implement classification algorithms effectively. Mastery of these techniques is essential for tasks like training classifiers to differentiate between image elements.
Avatrin
Messages
242
Reaction score
6
Hi

I have to run a few algorithms using Python on PNG-images. However, I also know that PNG is compressed... How do I do this? I need to learn the following:

1: Extracting the RGB information about the pixels.
2: Isolating parts of the image (for example, importing an image and only working on the lower half of the image)
3: Outputting images (since I have to run an algorithm on the original image and output the result)
 
Technology news on Phys.org
You have to convert it to a bitmap first. PNG can be compressed in a number of different ways so you can't just manipulate the raw bits, it's also line by line and sometimes even includes interlacing. Once you have a bitmap, it's much easier to manipulate, it's just a 2D array.
 
newjerseyrunner said:
You have to convert it to a bitmap first. PNG can be compressed in a number of different ways so you can't just manipulate the raw bits, it's also line by line and sometimes even includes interlacing. Once you have a bitmap, it's much easier to manipulate, it's just a 2D array.

Well, okay, I have converted my images to bitmap. Still, how do I do the rest?

It is an array, but how is it written? [[1 2 4][ 2 3 4]] Like this for a 1x2 pixel image?

How do I open it? How do I change it? Etc... What should I read to learn how to do that in Python?
 
You could look into PyPNG, PIL (Python Imaging Library), and OpenCV.
Which works best for you might depend on the specific tasks you need it to do.

I played around with PIL a while back... but I don't have a working knowledge with it.
I wonder if there is Python version of ImageJ (or interface to ImageJ).
 
Avatrin said:
Well, okay, I have converted my images to bitmap. Still, how do I do the rest?

It is an array, but how is it written? [[1 2 4][ 2 3 4]] Like this for a 1x2 pixel image?

How do I open it? How do I change it? Etc... What should I read to learn how to do that in Python?

I don't know what array you have, but how about these:
See what the type of the array is:
print type(myarray)
See what the first element of the array looks like:
print myarray[0]
See what the whole array looks like:
print myarray
Print the array's documentation string:
print myarray.__doc__
Same from the command line, if the array is the built-in array:
pydoc array
See what methods the array has
print dir(myarray)
 
Pillow is great:



You can alpha blend:

Python:
#!/usr/bin/python

from PIL import Image, ImageChops, ImageOpsNTONES=45
RATE=18
COLOR=(212,44,188)

f = open("./ton/map.ton", "r")
tones = f.read()
f.close()
nframes = len(tones) / NTONES

for itr in range(nframes):

    hit = [0] * NTONES
 
    img_base = Image.open("./subimg_inv/base_00.png")
 
    for lagitr in range(itr, itr - RATE, -1):
        if (lagitr < 0): break
     
     
        curtonemap = tones[lagitr * NTONES:(lagitr + 1) * NTONES]
     
     
        for aitr in range(NTONES):
         
            if curtonemap[aitr] == "1" and not hit[aitr] == 1:
                hit[aitr] = 1
             
                img_over = Image.open("./subimg/base_%02d.png" % (aitr + 1))
             
                img_over = img_over.convert("L")
             
                w = [0] * 3
                b = [0] * 3
                for citr in range(3):
                    b[citr] = COLOR[citr] - int((float(COLOR[citr]) * float((itr - lagitr))) / float(RATE))
             
             
                img_over = ImageOps.colorize(img_over, tuple(b), tuple(w))
             
             
                img_base = ImageChops.screen(img_base, img_over)
    print itr
 
    img_base = img_base.convert("RGB")
 
    img_base = ImageChops.invert(img_base)
 
    img_base.save("./frames/%08d.png" % itr)
 
Last edited:
ADDA said:
Pillow is great:



You can alpha blend:

Python:
#!/usr/bin/python

from PIL import Image, ImageChops, ImageOpsNTONES=45
RATE=18
COLOR=(212,44,188)

f = open("./ton/map.ton", "r")
tones = f.read()
f.close()
nframes = len(tones) / NTONES

for itr in range(nframes):

    hit = [0] * NTONES
 
    img_base = Image.open("./subimg_inv/base_00.png")
 
    for lagitr in range(itr, itr - RATE, -1):
        if (lagitr < 0): break
   
   
        curtonemap = tones[lagitr * NTONES:(lagitr + 1) * NTONES]
   
   
        for aitr in range(NTONES):
       
            if curtonemap[aitr] == "1" and not hit[aitr] == 1:
                hit[aitr] = 1
           
                img_over = Image.open("./subimg/base_%02d.png" % (aitr + 1))
           
                img_over = img_over.convert("L")
           
                w = [0] * 3
                b = [0] * 3
                for citr in range(3):
                    b[citr] = COLOR[citr] - int((float(COLOR[citr]) * float((itr - lagitr))) / float(RATE))
           
           
                img_over = ImageOps.colorize(img_over, tuple(b), tuple(w))
           
           
                img_base = ImageChops.screen(img_base, img_over)
    print itr
 
    img_base = img_base.convert("RGB")
 
    img_base = ImageChops.invert(img_base)
 
    img_base.save("./frames/%08d.png" % itr)

How does this answer the OP's questions?

If it doesn't, I will delete the post as being irrelevant to the thread.
 
ADDA said:
I was unsure whether the pixel data is processed individually or for the total image.

Well, I need to process pixel data individually since I am trying to learn machine learning.

Essentially, here's what I need to do:

1. Extract pixel data from an image and store it in a matrix which I then use to train a classifier.

2. Import another image which I test. Then I output an image according to how the classifier classified each individual pixel.

So, let's say I have a collection of portraits. I want to teach a classifier to recognize which part of the image is a face and which part is the background. There is contrast between the backgrounds and the faces, so I use pixel data. Then I test a, let's say 500 x 1000px, image. Now I want to output a 500 x 1000px picture which is colored in according to how the classifier classified the pixels in the test image:
the pixels that were classified as part of the face get colored yellow and the background pixels get colored blue.

How do I do this? (I only need help with the programming, not the mathematics)
 
  • #11
Avatrin said:
1. Extract pixel data from an image and store it in a matrix which I then use to train a classifier.

Python:
#!/usr/bin/python
#the above line invokes the python interpreter
#you must know python's location on your machine
#it is different on different platforms

import sys
from PIL import Image
#import from the python imaging library and sys library

if not len(sys.argv) == 2:
    print "USAGE:\n\n\t\tpython classify.py <input_img_path>\n"
    sys.exit()
#classify.py is argv[0] and argv[1] we will set to our input classifier's path (relative or absolute)

in_img_path = sys.argv[1]

img = Image.open(in_img_path)
#open the image using PIL

img = img.convert("RGB")
#reset the image parameter to ensure RGB colors

red_data = img.getdata(0)
#all the red pixels as a matrix

w,h = red_data.size
#set width and height parameters through a tuple assignment

print w, h
#check for correct dimensions

x = 10
y = 30
pixel_10x_30y = red_data[y * w + x]
print pixel_10x_30y

x = 100
y = 300
pixel_100x_300y = red_data[y * w + x]
print pixel_100x_300y

x = 10
y = 300
pixel_10x_300y = red_data[y * w + x]
print pixel_10x_300y

x = 10
y = 600
pixel_10x_600y = red_data[y * w + x]
print pixel_10x_600y

x = 100
y = 600
pixel_100x_600y = red_data[y * w + x]
print pixel_100x_600y

#quick check for me; pixels are arranged top to bottom left to rightgreen_data = img.getdata(1)
#all the green pixels as a matrixblue_data = img.getdata(2)
#all the blue pixels as a matrix

#all pixel values are whole number Integers in range [0,255]

#you can call img.getdata() (no args) to get a 3-tuple (RGB) of pixel information at each index of the array
#instead of 3 arrays of RGB values
Avatrin said:
Import another image which I test. Then I output an image according to how the classifier classified each individual pixel.
Python:
#/usr/bin/python

import sys
from PIL import Image, ImageChops

if not len(sys.argv) == 3:
    print "USAGE:\n\n\t\tpython output.py <in_img_path> <out_img_path>\n"
    sys.exit()
 
in_img_path = sys.argv[1]
out_img_path = sys.argv[2]

img_in = Image.open(in_img_path)

img_in = img_in.convert("RGB")r,g,b = img_in.split()
r = r.convert("1")
g = g.convert("1")
b = b.convert("1")

#yellow = r + g
#blue = b

classify_data_face = [0] * (img_in.size[0] * img_in.size[1])
classify_data_background = [1] * (img_in.size[0] * img_in.size[1])
#import your classification data here

img_classify_face = Image.new("1", img_in.size) #1 mode == binary mode
img_classify_face.putdata(classify_data_face)

img_classify_background = Image.new("1", img_in.size)
img_classify_background.putdata(classify_data_background)

r_new = ImageChops.logical_and(r,img_classify_face).convert("L")
g_new = ImageChops.logical_and(g,img_classify_face).convert("L")
b_new = ImageChops.logical_and(b,img_classify_background).convert("L")

out_img = Image.merge("RGB", (r_new,g_new,b_new)) #put the three channels back together

out_img.save(out_img_path)

#Basically, this code will turn an entire image blue as a background, without classification data
ORIGINAL:
medic.png
MODIFIED:
medici.png
 
Last edited:
  • Like
Likes Avatrin
  • #12
extra credit to guess who is in the postcard?
 
  • #13
Giuliano de' Medici
 
  • #14
ADDA said:
Python:
#!/usr/bin/python
#the above line invokes the python interpreter
#you must know python's location on your machine
#it is different on different platforms

import sys
from PIL import Image
#import from the python imaging library and sys library

if not len(sys.argv) == 2:
    print "USAGE:\n\n\t\tpython classify.py <input_img_path>\n"
    sys.exit()
#classify.py is argv[0] and argv[1] we will set to our input classifier's path (relative or absolute)

in_img_path = sys.argv[1]

img = Image.open(in_img_path)
#open the image using PIL

img = img.convert("RGB")
#reset the image parameter to ensure RGB colors

red_data = img.getdata(0)
#all the red pixels as a matrix

w,h = red_data.size
#set width and height parameters through a tuple assignment

print w, h
#check for correct dimensions

x = 10
y = 30
pixel_10x_30y = red_data[y * w + x]
print pixel_10x_30y

x = 100
y = 300
pixel_100x_300y = red_data[y * w + x]
print pixel_100x_300y

x = 10
y = 300
pixel_10x_300y = red_data[y * w + x]
print pixel_10x_300y

x = 10
y = 600
pixel_10x_600y = red_data[y * w + x]
print pixel_10x_600y

x = 100
y = 600
pixel_100x_600y = red_data[y * w + x]
print pixel_100x_600y

#quick check for me; pixels are arranged top to bottom left to rightgreen_data = img.getdata(1)
#all the green pixels as a matrixblue_data = img.getdata(2)
#all the blue pixels as a matrix

#all pixel values are whole number Integers in range [0,255]

#you can call img.getdata() (no args) to get a 3-tuple (RGB) of pixel information at each index of the array
#instead of 3 arrays of RGB values

Well, how can I get information for pixel (n,m) using getdata? Do I have to create a function for that? It looks like to me that getdata() gives me a one-dimensional list of three-tuples with x*y elements (so, essentially, a (x*y,3) matrix).
 

Similar threads

Replies
3
Views
3K
  • · Replies 1 ·
Replies
1
Views
3K
  • · Replies 6 ·
Replies
6
Views
2K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 17 ·
Replies
17
Views
3K
Replies
6
Views
3K
  • · Replies 9 ·
Replies
9
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K