[Image-SIG] Re: Image to MumPy array with PIL

Fredrik Lundh fredrik@pythonware.com
Thu, 22 Oct 1998 19:50:03 +0200


(cross-mailing to the image-sig -- as so often before, several people
posted very similar questions the very same day...)

Konrad Hinsen wrote:
>Forced by the need to extract data from a scanned image, I finally
>installed PIL, and was pleasantly surprised by it. It's rare to
>find packages that do what they promise and even come with decent
>documentation! I had my problem solved by 15 lines of code in
>10 minutes, so I have no reason to complain.

Glad you liked it!

>However, it would have been even easier to solve my problem if there
>were some way to obtain the pixel data in the form of a NumPy array.
>Maybe that exists, and I just didn't find it. If not, it would
>be a good idea for a future release. I ended up reading each pixel
>by getpixel(), which doesn't look particularly efficient.

I'm waiting for Guido to move the multiarray stuff into
the Python core distribution...

In the meantime, using tostring/fromstring is probably
the most efficient way to transfer data between PIL
and NumPy.

I'm not a regular NumPy-user, but something like the
following appears to work pretty well:

import Numeric, Image

def image2array(im):
    if im.mode not in ("L", "F"):
        raise ValueError, "can only convert single-layer images"
    if im.mode == "L":
        a = Numeric.fromstring(im.tostring(), Numeric.UnsignedInt8)
    else:
        a = Numeric.fromstring(im.tostring(), Numeric.Float32)
    a.shape = im.size[1], im.size[0]
    return a

def array2image(a):
    if a.typecode() == Numeric.UnsignedInt8:
        mode = "L"
    elif a.typecode() == Numeric.Float32:
        mode = "F"
    else:
        raise ValueError, "unsupported image mode"
    return Image.fromstring(mode, (a.shape[1], a.shape[0]), a.tostring())

Improvements or better solutions are welcome.

Cheers /F
fredrik@pythonware.com
http://www.pythonware.com