PIL 이미지를 numpy 배열로 변환하는 방법은 무엇입니까?


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)때문에), sizewidth x height또는 x * y행렬 순서는 동안 rows x columns.
foges

답변:


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

2
이것에 감사드립니다 ... Image.fromarrayPIL 문서 (!)에 나열되어 있지 않으므로 이것을 찾지 못했다면 결코 찾지 못했습니다.
Nathan Reed

13
이 페이지에는 numpy.asarray(pic)전환이 아닌 '적절한'전환 방법이 표시됩니다 numpy.array(pic). 당 이 답변 array 사본 반면 만들 asarray수 없습니다 (그러나 그 asarray결과가됩니다 읽기 전용).
Arthur Tacca

1
여기 내 경고 (내 실수로) : 데이터의 규모와 범위도 고려해야합니다. 많은 유스 케이스에서 0-255 바이트의 이미지를 렌더링하지만 numpy 배열에서 예를 들어 0.0-1.0으로 변환 될 것으로 예상 할 수 있습니다. uint8에서 일부 단위 변환은이 작업을 수행하지만이 경우에는 그렇지 않습니다. 확인하십시오 :)
BjornW

두 번째 답변이 더 좋습니다.
나단

193

I배열로 엽니 다 :

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

에 몇 가지 작업을 수행 I한 다음 이미지로 다시 변환하십시오.

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

FFT, Python으로 numpy 이미지 필터링

어떤 이유로 명시 적으로 수행하려는 경우 correlation.zip 의이 페이지 에서 getdata ()를 사용하는 pil2array () 및 array2pil () 함수가 있습니다.


2
@ArditS .: import Image먼저 했습니까 ? PIL이 설치되어 있습니까?
endolith

5
는 IS uint8변환이 필요?
Neil Traft

4
numpy.asarray(Image.open(filename)).jpg 이미지에서는 작동하지만 .png에서는 작동하지 않는 것 같습니다. 결과는로 표시됩니다 array(<PngImagePlugin.PngImageFile image mode=LA size=500x500 at 0x3468198>, dtype=object). 이 PngImagePlugin.PngImageFile문제를 해결하기 위해 분명히 명명 된 방법이없는 것 같습니다 . 나는 이것을 새로운 질문으로해야한다고 생각하지만 그것은이 스레드와 매우 관련이 있습니다. 아무도 여기서 무슨 일이 일어나고 있는지 이해합니까?
jez December

3
@Rebs : 이것이 훨씬 더 빠른 이유 입니다 : getdata()object ( pillow.readthedocs.io/en/3.4.x/reference/… ) 와 같은 시퀀스를 반환 하지만 베개 이미지 는 원시 바이트에 액세스하는 데 사용할 수 있는 __array_interface__것을 구현합니다 numpy반복자를 거치지 않고 이미지의 이미지 ( github.com/python-pillow/Pillow/blob/…docs.scipy.org/doc/numpy/reference/arrays.interface.html 참조 ) 당신은 심지어 사용할 수 있습니다numpy.array(PIL.Image.open('test.jpg'))
tdp2110

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)

주의해야 할 사항 중 하나는 필로우 스타일 im이 열 주요이고 numpy 스타일 im2arr이 행 주요이라는 것입니다. 그러나 함수는 Image.fromarray이미 이것을 고려합니다. 이고, 그 arr2im.size == im.sizearr2im.mode == im.mode상술 한 예이다.

변환 된 numpy 배열을 처리 할 때 HxWxC 데이터 형식을 처리해야합니다 (예 : 변환 im2arr = np.rollaxis(im2arr, 2, 0)또는im2arr = np.transpose(im2arr, (2, 0, 1)) CxHxW 형식으로).


2
이것은 import 문을 포함하여 가장 깨끗한 예에 관한 것입니다 (세부 사항에 대한 감사). 이 답변에 투표하여 가시성을 높이십시오.
David Parks

PIL 그린 이미지를 numpy 배열로 변환 할 때 matplotlib imshow를 배열에 사용할 때 뒤집어 야하는 np.flipud것을 수정 해야한다는 것을 알았습니다. 내 PIL 이미지는을 사용하여 처음부터 작성되었지만 ImageDraw.Draw. 좌표의 원점이 어디에서 오는지주의해야한다고 생각합니다.
CMCDragonkai

축복합니다!! 나는 반나절 동안이 답변을 찾고 있습니다. 플롯 이미지 후 원래 축을 원래 축으로 복원하는 문제를 해결합니다.
Tinkerbell 2016 년

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

그 후 신경 네트워크에서 byteArrays를 사용할 수있었습니다.

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.