PIL : How to write array to image ???

M

Martin

Dear group

I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.

I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:

[[ 200. 200. 200. ..., 0. 0. 0.]
[ 200. 200. 200. ..., 0. 0. 0.]
[ 200. 200. 200. ..., 0. 0. 0.]
...,
[ 0. 0. 0. ..., 200. 200. 200.]
[ 0. 0. 0. ..., 200. 200. 200.]
[ 0. 0. 0. ..., 200. 200. 200.]]

But the image looks nothing like that.

Please see the images on:
http://hvidberg.net/Martin/temp/quat_col.png
http://hvidberg.net/Martin/temp/quat_bw.png

or run the code to see them locally.

Please – what do I do wrong in the PIL part ???

:-? Martin



import numpy as np
from PIL import Image
from PIL import ImageOps

maxcol = 100
maxrow = 100

a = np.zeros((maxcol,maxrow),float)

for i in range(maxcol):
for j in range(maxrow):
if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
a[i,j] = 200
else:
a[i,j] = 0

print a

pilImage = Image.fromarray(a,'RGB')
pilImage.save('quat_col.png')
pilImage = ImageOps.grayscale(pilImage)
pilImage.save('quat_bw.png')
 
R

Robert Kern

Martin said:
Dear group

I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.

I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:

[[ 200. 200. 200. ..., 0. 0. 0.]
[ 200. 200. 200. ..., 0. 0. 0.]
[ 200. 200. 200. ..., 0. 0. 0.]
...,
[ 0. 0. 0. ..., 200. 200. 200.]
[ 0. 0. 0. ..., 200. 200. 200.]
[ 0. 0. 0. ..., 200. 200. 200.]]

But the image looks nothing like that.

Please see the images on:
http://hvidberg.net/Martin/temp/quat_col.png
http://hvidberg.net/Martin/temp/quat_bw.png

or run the code to see them locally.

Please – what do I do wrong in the PIL part ???

:-? Martin



import numpy as np
from PIL import Image
from PIL import ImageOps

maxcol = 100
maxrow = 100

a = np.zeros((maxcol,maxrow),float)

for i in range(maxcol):
for j in range(maxrow):
if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
a[i,j] = 200
else:
a[i,j] = 0

print a

pilImage = Image.fromarray(a,'RGB')

You are telling it the wrong mode information. If you want an RGB image, you
need to give it a uint8 array with shape (height, width, 3). Exactly what are
you trying to do? I can't infer that from your code.

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco
 
P

Peter Otten

Martin said:
Dear group

I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.

I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:

[[ 200. 200. 200. ..., 0. 0. 0.]
[ 200. 200. 200. ..., 0. 0. 0.]
[ 200. 200. 200. ..., 0. 0. 0.]
...,
[ 0. 0. 0. ..., 200. 200. 200.]
[ 0. 0. 0. ..., 200. 200. 200.]
[ 0. 0. 0. ..., 200. 200. 200.]]

But the image looks nothing like that.

Please see the images on:
http://hvidberg.net/Martin/temp/quat_col.png
http://hvidberg.net/Martin/temp/quat_bw.png

or run the code to see them locally.

Please – what do I do wrong in the PIL part ???

:-? Martin



import numpy as np
from PIL import Image
from PIL import ImageOps

maxcol = 100
maxrow = 100

a = np.zeros((maxcol,maxrow),float)

for i in range(maxcol):
for j in range(maxrow):
if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
a[i,j] = 200
else:
a[i,j] = 0

print a

pilImage = Image.fromarray(a,'RGB')
pilImage.save('quat_col.png')
pilImage = ImageOps.grayscale(pilImage)
pilImage.save('quat_bw.png')

The PIL seems to copy the array contents directly from memory without any
conversions or sanity check. In your example The float values determine the
gray value of 8 consecutive pixels.

If you want a[i,j] to become the color of the pixel (i, j) you have to use
an array with a memory layout that is compatible to the Image.
Here are a few examples:
import numpy
from PIL import Image
a = numpy.zeros((100, 100), numpy.uint8)
a[:50, :50] = a[50:, 50:] = 255
Image.fromarray(a).save("tmp1.png")
b = numpy.zeros((100, 100, 3), numpy.uint8)
b[:50, :50, :] = b[50:, 50:, :] = [255, 0, 0]
Image.fromarray(b).save("tmp2.png")
c = numpy.zeros((100, 100), numpy.uint32)
c[:50, :50] = c[50:, 50:] = 0xff808000
Image.fromarray(c, "RGBA").save("tmp3.png")

Peter
 
M

Martin

Martin said:
Dear group
I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.
I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:
[[ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 ...,
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]]
But the image looks nothing like that.
or run the code to see them locally.
Please – what do I do wrong in the PIL part ???
:-? Martin
import numpy as np
from PIL import Image
from PIL import ImageOps
maxcol = 100
maxrow = 100
a = np.zeros((maxcol,maxrow),float)
for i in range(maxcol):
    for j in range(maxrow):
        if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
            a[i,j] = 200
        else:
            a[i,j] = 0
pilImage = Image.fromarray(a,'RGB')
pilImage.save('quat_col.png')
pilImage = ImageOps.grayscale(pilImage)
pilImage.save('quat_bw.png')

The PIL seems to copy the array contents directly from memory without any
conversions or sanity check. In your example The float values determine the
gray value of 8 consecutive pixels.

If you want a[i,j] to become the color of the pixel (i, j) you have to use
an array with a memory layout that is compatible to the Image.
Here are a few examples:
import numpy
from PIL import Image
a = numpy.zeros((100, 100), numpy.uint8)
a[:50, :50] = a[50:, 50:] = 255
Image.fromarray(a).save("tmp1.png")
b = numpy.zeros((100, 100, 3), numpy.uint8)
b[:50, :50, :] = b[50:, 50:, :] = [255, 0, 0]
Image.fromarray(b).save("tmp2.png")
c = numpy.zeros((100, 100), numpy.uint32)
c[:50, :50] = c[50:, 50:] = 0xff808000
Image.fromarray(c, "RGBA").save("tmp3.png")

Peter

Thanks All - That helped a lot...

The working code ended with:


imga = np.zeros((imgL.shape[1],imgL.shape[0]),np.uint8)
for ro in range(imgL.shape[1]):
for co in range(imgL.shape[0]):
imga[ro,co] = imgL[ro,co]
Image.fromarray(imga).save('_a'+str(lev)+'.png')
 
M

Mart.

Martin said:
Dear group
I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.
I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:
[[ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 ...,
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]]
But the image looks nothing like that.
Please see the images on:
http://hvidberg.net/Martin/temp/quat_col.png
http://hvidberg.net/Martin/temp/quat_bw.png
or run the code to see them locally.
Please – what do I do wrong in the PIL part ???
:-? Martin
import numpy as np
from PIL import Image
from PIL import ImageOps
maxcol = 100
maxrow = 100
a = np.zeros((maxcol,maxrow),float)
for i in range(maxcol):
    for j in range(maxrow):
        if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
            a[i,j] = 200
        else:
            a[i,j] = 0
print a
pilImage = Image.fromarray(a,'RGB')
pilImage.save('quat_col.png')
pilImage = ImageOps.grayscale(pilImage)
pilImage.save('quat_bw.png')
The PIL seems to copy the array contents directly from memory without any
conversions or sanity check. In your example The float values determine the
gray value of 8 consecutive pixels.
If you want a[i,j] to become the color of the pixel (i, j) you have to use
an array with a memory layout that is compatible to the Image.
Here are a few examples:
import numpy
from PIL import Image
a = numpy.zeros((100, 100), numpy.uint8)
a[:50, :50] = a[50:, 50:] = 255
Image.fromarray(a).save("tmp1.png")
b = numpy.zeros((100, 100, 3), numpy.uint8)
b[:50, :50, :] = b[50:, 50:, :] = [255, 0, 0]
Image.fromarray(b).save("tmp2.png")
c = numpy.zeros((100, 100), numpy.uint32)
c[:50, :50] = c[50:, 50:] = 0xff808000
Image.fromarray(c, "RGBA").save("tmp3.png")

Thanks All - That helped a lot...

The working code ended with:

        imga = np.zeros((imgL.shape[1],imgL.shape[0]),np.uint8)
        for ro in range(imgL.shape[1]):
            for co in range(imgL.shape[0]):
                imga[ro,co] = imgL[ro,co]
        Image.fromarray(imga).save('_a'+str(lev)+'.png')

Without knowing how big your image is (can't remember if you said!).
Perhaps rather than looping in the way you might in C for example, the
numpy where might be quicker if you have a big image. Just a
thought...
 
M

Martin

Martin wrote:
Dear group
I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.
I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:
[[ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 ...,
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]]
But the image looks nothing like that.
Please see the images on:
http://hvidberg.net/Martin/temp/quat_col.png
http://hvidberg.net/Martin/temp/quat_bw.png
or run the code to see them locally.
Please – what do I do wrong in the PIL part ???
:-? Martin
import numpy as np
from PIL import Image
from PIL import ImageOps
maxcol = 100
maxrow = 100
a = np.zeros((maxcol,maxrow),float)
for i in range(maxcol):
    for j in range(maxrow):
        if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
            a[i,j] = 200
        else:
            a[i,j] = 0
print a
pilImage = Image.fromarray(a,'RGB')
pilImage.save('quat_col.png')
pilImage = ImageOps.grayscale(pilImage)
pilImage.save('quat_bw.png')
The PIL seems to copy the array contents directly from memory without any
conversions or sanity check. In your example The float values determine the
gray value of 8 consecutive pixels.
If you want a[i,j] to become the color of the pixel (i, j) you have to use
an array with a memory layout that is compatible to the Image.
Here are a few examples:
import numpy
from PIL import Image
a = numpy.zeros((100, 100), numpy.uint8)
a[:50, :50] = a[50:, 50:] = 255
Image.fromarray(a).save("tmp1.png")
b = numpy.zeros((100, 100, 3), numpy.uint8)
b[:50, :50, :] = b[50:, 50:, :] = [255, 0, 0]
Image.fromarray(b).save("tmp2.png")
c = numpy.zeros((100, 100), numpy.uint32)
c[:50, :50] = c[50:, 50:] = 0xff808000
Image.fromarray(c, "RGBA").save("tmp3.png")
Peter
Thanks All - That helped a lot...
The working code ended with:
        imga = np.zeros((imgL.shape[1],imgL.shape[0]),np.uint8)
        for ro in range(imgL.shape[1]):
            for co in range(imgL.shape[0]):
                imga[ro,co] = imgL[ro,co]
        Image.fromarray(imga).save('_a'+str(lev)+'.png')

Without knowing how big your image is (can't remember if you said!).
Perhaps rather than looping in the way you might in C for example, the
numpy where might be quicker if you have a big image. Just a
thought...

And a good thought too... I use to teach ansi C at Univ. many ears
ago, and it's still one of my favorits. But I prefere Python for this
type of work. Python have a much faster develop time, is much easier
to write (fewer linees, simpler syntax) and is much more 'hot' in
these days. Finally my favorit GIS and RS applications support Python
out-of-the-box.

:) Martin
 
M

Mart.

Martin wrote:
Dear group
I'm trying to use PIL to write an array (a NumPy array to be exact) to
an image.
Peace of cake, but it comes out looking strange.
I use the below mini code, that I wrote for the purpose. The print of
a looks like expected:
[[ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 [ 200.  200.  200. ...,    0.    0.    0.]
 ...,
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]
 [   0.    0.    0. ...,  200.  200.  200.]]
But the image looks nothing like that.
Please see the images on:
http://hvidberg.net/Martin/temp/quat_col.png
http://hvidberg.net/Martin/temp/quat_bw.png
or run the code to see them locally.
Please – what do I do wrong in the PIL part ???
:-? Martin
import numpy as np
from PIL import Image
from PIL import ImageOps
maxcol = 100
maxrow = 100
a = np.zeros((maxcol,maxrow),float)
for i in range(maxcol):
    for j in range(maxrow):
        if (i<(maxcol/2) and j<(maxrow/2)) or (i>=(maxcol/2) and j>=
(maxrow/2)):
            a[i,j] = 200
        else:
            a[i,j] = 0
print a
pilImage = Image.fromarray(a,'RGB')
pilImage.save('quat_col.png')
pilImage = ImageOps.grayscale(pilImage)
pilImage.save('quat_bw.png')
The PIL seems to copy the array contents directly from memory without any
conversions or sanity check. In your example The float values determine the
gray value of 8 consecutive pixels.
If you want a[i,j] to become the color of the pixel (i, j) you have to use
an array with a memory layout that is compatible to the Image.
Here are a few examples:
import numpy
from PIL import Image
a = numpy.zeros((100, 100), numpy.uint8)
a[:50, :50] = a[50:, 50:] = 255
Image.fromarray(a).save("tmp1.png")
b = numpy.zeros((100, 100, 3), numpy.uint8)
b[:50, :50, :] = b[50:, 50:, :] = [255, 0, 0]
Image.fromarray(b).save("tmp2.png")
c = numpy.zeros((100, 100), numpy.uint32)
c[:50, :50] = c[50:, 50:] = 0xff808000
Image.fromarray(c, "RGBA").save("tmp3.png")
Peter
Thanks All - That helped a lot...
The working code ended with:
        imga = np.zeros((imgL.shape[1],imgL.shape[0]),np.uint8)
        for ro in range(imgL.shape[1]):
            for co in range(imgL.shape[0]):
                imga[ro,co] = imgL[ro,co]
        Image.fromarray(imga).save('_a'+str(lev)+'.png')
Without knowing how big your image is (can't remember if you said!).
Perhaps rather than looping in the way you might in C for example, the
numpy where might be quicker if you have a big image. Just a
thought...

And a good thought too... I use to teach ansi C at Univ. many ears
ago, and it's still one of my favorits. But I prefere Python for this
type of work. Python have a much faster develop time, is much easier
to write (fewer linees, simpler syntax) and is much more 'hot' in
these days. Finally my favorit GIS and RS applications support Python
out-of-the-box.

:) Martin

I wasn't advocating doing it in c just that you could speed up your
program considerably by not looping and using some of the numpy array
options.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,744
Messages
2,569,484
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top