PILイメージを派手な配列に変換する方法は?


257

わかりました、PIL画像オブジェクトをnumpy配列に前後に変換するので、PILのPixelAccessオブジェクトが許可するよりも速いピクセル単位のピクセル変換を行うことができます。次の方法で、ピクセル情報を便利な3D numpy配列に配置する方法を理解しました。

pic = Image.open("foo.jpg")
pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)

しかし、すごい変換をすべて実行した後、それをPILオブジェクトに読み込む方法を理解できないようです。私はそのputdata()方法を知っていますが、動作するようには思えません。


6
ことを注意pic.size[0]してpic.size[1]スワップする必要があります(すなわち。reshape(pic.size[1], pic.size[0], 3))、以来sizeであるwidth x heightか、x * y行列の順序がある一方で、rows x columns
fogeは、

回答:


286

正確にputdata()動作していないとは言っていません。あなたがやっていると思います

>>> pic.putdata(a)
Traceback (most recent call last):
  File "...blablabla.../PIL/Image.py", line 1185, in putdata
    self.im.putdata(data, scale, offset)
SystemError: new style getargs format but argument is not a tuple

これはputdata、タプルのシーケンスを想定していて、numpy配列を与えているためです。この

>>> data = list(tuple(pixel) for pixel in pix)
>>> pic.putdata(data)

動作しますが、非常に遅いです。

PIL 1.1.6以降、画像とnumpy配列を変換する「適切な」方法は単純です

>>> pix = numpy.array(pic)

結果の配列はあなたのものとは異なる形式です(この場合、3次元配列または行/列/ rgb)。

次に、配列に変更を加えた後、をpic.putdata(pix)使用するか、で新しいイメージを作成できるようになりますImage.fromarray(pix)


2
まず、pic.putdata(data)にすべきではありませんか?そして、numpy.asarray(pic)は読み取り専用の配列を生成するため、numpy.array(pic)を呼び出す必要があり、質問に答えませんでした... pic = Image.fromarray( pix)。あなたの答えを修正し、私はそれを受け入れます。
akdom 2008

2
このおかげで... Image.fromarrayPILドキュメント(!)に記載されていないので、そうでなければ、私はそれを見つけることができませんでした。
ネイサンリード、

13
そのページはnumpy.asarray(pic)、変換ではなく「適切な」方法としてリストされていnumpy.array(pic)ます。この回答に よれarrayば、コピーは作成されますが作成asarrayされません(ただし、asarray結果は読み取り専用になります)。
Arthur Tacca 2016年

1
ここでの警告(私自身の間違いによる):データのスケールと範囲も考慮する必要があります。多くのユースケースでは、画像を0〜255バイトでレンダリングしますが、これらはnumpy配列でたとえば0.0〜1.0に変換されると予想される場合があります。uint8からの一部の単位変換はこれを行いますが、この場合は行いません。そのため、それを確認してください:)
BjornW

2番目の答えの方が優れています。
ネイサン

193

I配列として開く:

>>> I = numpy.asarray(PIL.Image.open('test.jpg'))

いくつかIの処理を行ってから、画像に変換し直します。

>>> im = PIL.Image.fromarray(numpy.uint8(I))

FFT、Pythonで派手な画像をフィルタリングする

何らかの理由で明示的に実行したい場合は、このページの correlation.zipにgetdata()を使用するpil2array()およびarray2pil()関数があります


2
@ArditS .:あなたはimport Image最初にいましたか?PILはインストールされていますか?
エンドリス2013年

5
あるuint8変換が必要?
Neil Traft 2014年

4
numpy.asarray(Image.open(filename)).jpg画像では機能するようですが、.pngでは機能しません。結果はとして表示されarray(<PngImagePlugin.PngImageFile image mode=LA size=500x500 at 0x3468198>, dtype=object)ます。これPngImagePlugin.PngImageFileを解決するためのオブジェクトの明確な名前のメソッドはないようです。私はこれを新しい質問として尋ねるべきだと思いますが、それはこのスレッドに非常に関連しています。誰かがここで何がうまくいかないのか理解していますか?
jez

3
@Rebs:ここに理由です理由:これはそんなに速くなるgetdata()オブジェクト(のようなリターンシーケンスpillow.readthedocs.io/en/3.4.x/reference/...)が、枕の画像が実装生のバイトにアクセスするために使用することができますが、イテレーターを通過する必要のない画像の例(github.com/python-pillow/Pillow/blob/…およびdocs.scipy.org/doc/numpy/reference/arrays.interface.htmlを参照)そのまま使用することもできます__array_interface__numpynumpy.array(PIL.Image.open('test.jpg'))
tdp2110 2017

3
@jez numpyに変換する前に、Imageオブジェクトが閉じているかどうかを確認します。同じことが私にも起こり、画像オブジェクトをどこかで閉じました。
Shaohua Li

65

Python 3.5でPillow 4.1.1(PILの後継)を使用しています。Pillowとnumpyの間の変換は簡単です。

from PIL import Image
import numpy as np
im = Image.open('1.jpg')
im2arr = np.array(im) # im2arr.shape: height x width x channel
arr2im = Image.fromarray(im2arr)

注意が必要なことの1つは、枕スタイルimが列優先であり、numpyスタイルim2arrが行優先であることです。ただし、関数はImage.fromarrayすでにこれを考慮しています。つまり、arr2im.size == im.sizeそしてarr2im.mode == im.mode上記の例では。

変換されたnumpy配列を処理するときは、HxWxCデータ形式に注意するim2arr = np.rollaxis(im2arr, 2, 0)必要im2arr = np.transpose(im2arr, (2, 0, 1))があります。たとえば、変換またはCxHxW形式に変換します。


2
これは、インポートステートメントを含む最もクリーンな例についてです(その詳細に感謝します)。可視性を高めるためにこの回答に投票しましょう。
デビッドパークス

PIL描画イメージを派手な配列に変換したときに、配列でmatplotlib imshowを使用すると、np.flipud修正が必要な逆さまになっていることがわかりました。私のPILイメージはを使用してゼロから作成されましたがImageDraw.Draw。彼らの座標の原点がどこから来ているのか注意する必要があると思います。
CMCDragonkai 2018

お大事に!!私はこの答えを半日探していました。プロット画像の元の軸を元の軸に復元するという私の問題を解決します。
ティンカーベル2018年

16

あなたはこの方法で画像をnumpy配列に変換する必要があります:

import numpy
import PIL

img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img) 

この変換方法では画像は保持されますが、色が失われます。とにかく色落ちを避けるには?
Moondra

7
@moondra私はあなたの質問を理解していれば、あなたは置き換えることができます.convert("L") .convert("RGB")
Billal Begueradj

3

例として、私は今日使用しました:

import PIL
import numpy
from PIL import Image

def resize_image(numpy_array_image, new_height):
    # convert nympy array image to PIL.Image
    image = Image.fromarray(numpy.uint8(numpy_array_image))
    old_width = float(image.size[0])
    old_height = float(image.size[1])
    ratio = float( new_height / old_height)
    new_width = int(old_width * ratio)
    image = image.resize((new_width, new_height), PIL.Image.ANTIALIAS)
    # convert PIL.Image into nympy array back again
    return array(image)

0

画像がBlob形式(つまり、データベース)で保存されている場合、Billal Begueradjによって説明されているのと同じ手法を使用して、画像をBlobからバイト配列に変換できます。

私の場合、dbテーブルのblob列に格納されている画像が必要でした。

def select_all_X_values(conn):
    cur = conn.cursor()
    cur.execute("SELECT ImageData from PiecesTable")    
    rows = cur.fetchall()    
    return rows

次に、データセットをnp.arrayに変更するヘルパー関数を作成しました。

X_dataset = select_all_X_values(conn)
imagesList = convertToByteIO(np.array(X_dataset))

def convertToByteIO(imagesArray):
    """
    # Converts an array of images into an array of Bytes
    """
    imagesList = []

    for i in range(len(imagesArray)):  
        img = Image.open(BytesIO(imagesArray[i])).convert("RGB")
        imagesList.insert(i, np.array(img))

    return imagesList

この後、自分のニューラルネットワークでbyteArrayを使用することができました。

plt.imshow(imagesList[0])

0

Numpy to PIL画像を変換してPIL to Numpy

import numpy as np
from PIL import Image

def pilToNumpy(img):
    return np.array(img)

def NumpyToPil(img):
    return Image.fromarray(img)

-1
def imshow(img):
    img = img / 2 + 0.5     # unnormalize
    npimg = img.numpy()
    plt.imshow(np.transpose(npimg, (1, 2, 0)))
    plt.show()

機能を圧縮した後、画像をnumpy()関数に解析することにより、画像をnumpyに変換できます(非正規化)

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.