Working with PNG images in Python

In summary: PIL import Image, ImageChops, ImageOpsNTONES=45RATE=18COLOR=(212,44,188)f = open("./ton/map.ton", "r")tones = f.read()f.close()nframes = len(tones) / NTONESfor itr in
  • #1
Avatrin
245
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
  • #2
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.
 
  • #3
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?
 
  • #4
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).
 
  • #5
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)
 
  • #6
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:
  • #7
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.
 
  • #9
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).
 

1. How do I open and read a PNG image in Python?

To open and read a PNG image in Python, you can use the Pillow library. First, install Pillow using the command "pip install Pillow" in your terminal. Then, import the library in your code using the statement "from PIL import Image". Finally, use the Image.open() method to open the PNG file and store it in a variable. You can then use this variable to perform operations on the image.

2. How can I resize a PNG image in Python?

To resize a PNG image in Python, you can use the resize() method from the Pillow library. After opening the image using the Image.open() method, call the resize() method with the desired dimensions as parameters. The resized image will be returned as an object, which you can then save or display.

3. How do I convert a PNG image to a different file format in Python?

To convert a PNG image to a different file format in Python, you can use the save() method from the Pillow library. After opening the image using the Image.open() method, call the save() method and specify the desired file format as a parameter, such as "JPEG" or "GIF". This will create a new file with the converted image in the specified format.

4. Can I add text or other elements to a PNG image using Python?

Yes, you can add text or other elements to a PNG image using Python and the Pillow library. After opening the image using the Image.open() method, you can use methods like ImageDraw() and ImageFont() to create text or shapes. These elements can then be added to the image using the paste() method.

5. How can I manipulate the colors of a PNG image in Python?

To manipulate the colors of a PNG image in Python, you can use the ImageColor and ImageEnhance modules from the Pillow library. ImageColor allows you to convert colors to different formats, while ImageEnhance allows you to adjust brightness, contrast, and other color attributes of the image. You can also use the ImageOps module to apply filters and transformations to the image.

Similar threads

  • Programming and Computer Science
Replies
3
Views
1K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
6
Views
1K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
1
Views
1K
  • Programming and Computer Science
Replies
9
Views
1K
  • Programming and Computer Science
Replies
7
Views
388
  • Programming and Computer Science
Replies
12
Views
1K
  • Programming and Computer Science
Replies
17
Views
1K
  • Programming and Computer Science
Replies
2
Views
1K
Back
Top