Working with PNG images in Python

Click For Summary

Discussion Overview

The discussion revolves around working with PNG images in Python, focusing on extracting pixel data, manipulating images, and utilizing libraries for image processing. Participants explore various methods for handling PNG images, including converting to bitmap format, accessing pixel data, and applying algorithms for image classification.

Discussion Character

  • Exploratory
  • Technical explanation
  • Homework-related
  • Mathematical reasoning

Main Points Raised

  • One participant inquires about extracting RGB information from PNG images and isolating parts of the image for processing.
  • Another participant suggests converting PNG images to bitmap format for easier manipulation due to the complexities of PNG compression.
  • Several participants discuss the use of libraries such as PyPNG, PIL (Pillow), and OpenCV for image processing tasks, noting that the choice may depend on specific needs.
  • A participant shares a code snippet demonstrating how to alpha blend images using Pillow, raising questions about its relevance to the original inquiry.
  • One participant expresses uncertainty about whether pixel data should be processed individually or collectively, indicating a need for individual pixel manipulation for machine learning purposes.
  • Another participant outlines a specific use case involving training a classifier to distinguish between faces and backgrounds in images, seeking programming assistance rather than mathematical guidance.
  • A code example is provided that demonstrates how to extract pixel data from an image and access specific pixel values using Pillow.

Areas of Agreement / Disagreement

Participants generally agree on the utility of libraries like Pillow for image manipulation, but there are differing opinions on the best approach to processing pixel data, particularly regarding individual versus total image processing. The discussion remains unresolved regarding the specific implementation details for the original poster's needs.

Contextual Notes

Some participants mention the complexities of PNG compression and the need for conversion to bitmap format, but there are no settled assumptions or definitions regarding the best practices for image processing in Python.

Who May Find This Useful

This discussion may be useful for individuals interested in image processing, particularly those working with Python and looking to manipulate PNG images for applications in machine learning or algorithm development.

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   Reactions: 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
3K
  • · Replies 2 ·
Replies
2
Views
3K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 17 ·
Replies
17
Views
3K
Replies
6
Views
3K
  • · Replies 2 ·
Replies
2
Views
2K
  • · Replies 1 ·
Replies
1
Views
2K