[Image-SIG] [SPAM] - Re: fromarray rotates image - Email found in subject

Cousoulis, Paul pcousoulis at meso-scale.com
Tue Jan 31 22:15:36 CET 2012


The second image is a 32 bit tif, so you need to use something like ImageJ or Fiji. Microsoft image viewer won't work. I think I shouldn't have to fiddle with the row/column order, but I guess  it needs to stay the way it is. Thanks for the help.

Paul

-----Original Message-----
From: Chris Barker [mailto:chris.barker at noaa.gov] 
Sent: Tuesday, January 31, 2012 1:18 PM
To: Cousoulis, Paul; image-sig at python.org
Subject: [SPAM] - Re: [Image-SIG] fromarray rotates image - Email found in subject

<putting the image-sig list back on the thread... >

On Tue, Jan 31, 2012 at 8:38 AM, Cousoulis, Paul <pcousoulis at meso-scale.com> wrote:
> I'm sorry but I still think there is a bug.

I still don't think so: explanation below.

By the way, there is another problem with your example -- I get an all-black second image. I think you need to specify the image mode when you create the new image:

newimage = Image.fromarray(npArray, mode=image1.mode)

though that still makes a mess of it! -- more debugging to be done here -- see below

> In [4]: print image1.size
> (516, 356)
>
> In [5]: npArray = np.array(image1.getdata())
>
> In [6]: print npArray.shape
> (183696L,)

OK so far


> In [7]: npArray.shape = image1.size

> In [8]: print npArray.shape
> (516L, 356L)

here I would swap -- as numpy naturally stores data the other way:

and now it works:

In [8]: run pil-numpy-test.py
<PIL.TiffImagePlugin.TiffImageFile image mode=L size=516x356 at 0x3A86468> input image size: (516, 356) numpy image shape before: (183696,) numpy image shape after: (356, 516) <PIL.Image.Image image mode=L size=516x356 at 0x176C1E8> new image size (516, 356)

(though the colors are still screwed up -- I don't know what's up with that...)

I can see how you'd expect it to work the way you had it, but I think the problem is that you are mixing two ways to push raw data to/froim numpy arrays:

npArray = np.array(image1.getdata())

is using PIL's getdata() to put the raw data in a string, then turning that into a numpy array (oh, and that may be the source of teh data mess up too...np.array is expecting a sequence of numbers or something, not raw data -- you want:

OOPS, actually, getdata returns something else altogether:

"""
getdata

im.getdata() => sequence

Returns the contents of an image as a sequence object containing pixel values. The sequence object is flattened, so that values for line one follow directly after the values of line zero, and so on.

Note that the sequence object returned by this method is an internal PIL data type, which only supports certain sequence operations, including iteration and basic sequence access. To convert it to an ordinary sequence (e.g. for printing), use list(im.getdata()).
"""
so it should be:

npArray = np.fromstring(image1.tostring(), dtype=np.uint8)

npArray.shape = (image1.size[1], image1.size[0] )

and that now works -- correct size, and correct final image.

However:

newimage = Image.fromarray(npArray)

is using the numpy "array protocol", which is a bit different than fromstring/tostring -- it carries shape information -- hence the need to specify the shape of the numpy array as I did.

you can use that protocol both ways:

npArray = np.asarray(image1)

which then preserved size info.

Here's my new version:

from PIL import Image
import numpy as np


image1 = Image.open("LineGraph.tif")
print image1
print "input image size:", image1.size

npArray = np.asarray(image1)

print "numpy image shape after:", npArray.shape

newimage = Image.fromarray(npArray, mode=image1.mode)

print newimage
print "new image size", newimage.size

newimage.save("LineGraph2.tif")


NOTE: if you do fromstring/tostring (or tobuffer) consistently, then it doesn't matter what shape you make the numpy array:


image1 = Image.open("LineGraph.tif")
print image1
print "input image size:", image1.size

npArray = np.fromstring(image1.tostring(), dtype=np.uint8)

print "numpy image shape:", npArray.shape

newimage = Image.fromstring(image1.mode, image1.size, npArray.tostring())

print newimage
print "new image size", newimage.size

newimage.save("LineGraph2.tif")

But that's less efficient, and messier.

NOTE: it might have been nicer if the array protocol were used such that the array created was fortran-order, and thus (w,h) in shape, but so it goes.

HTH,

   -Chris




-- 

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker at noaa.gov


====================================================================== 
 This electronic message transmission and any attachments are 
 confidential and/or proprietary and may constitute legally privileged information of 
 Meso Scale Diagnostics, LLC. The information is intended for solely 
 the use of recipient (recipient).  If you are not 
 the intended recipient, you are hereby notified that any 
 disclosure, copying, distribution or the taking of any action in 
 reliance of this information is strictly prohibited. You are not 
 authorized to retain it in any form nor to re-transmit it, and 
 you should destroy this email immediately. 

 If you have received this electronic transmission in error, 
 please notify us by telephone (240-631-2522) or by electronic 
 mail to the sender of this email, Cousoulis, Paul (pcousoulis at meso-scale.com),
 immediately. 
 ===================================================================== 




More information about the Image-SIG mailing list