Как преобразовать изображение PIL в массив numpy?
Хорошо, я собираюсь с преобразованием объекта изображения 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()
, но не могу заставить его себя вести.
Ответы
Ответ 1
Вы не говорите, как именно 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
Откройте I
как массив:
>>> I = numpy.asarray(PIL.Image.open('test.jpg'))
Сделайте что-нибудь в I
, а затем верните его в изображение:
>>> im = PIL.Image.fromarray(numpy.uint8(I))
Фильтровать изображения numpy с помощью FFT, Python
Если вы хотите сделать это явно по какой-либо причине, есть функции pil2array() и array2pil(), используя getdata() на эту страницу в корреляции. zip.
Ответ 3
Я использую подушку 4.1.1 (преемник PIL) в Python 3.5. Преобразование между Подушкой и 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
является основным столбцом, в то время как стиль im2arr
стиле im2arr
является im2arr
строкой. Однако функция Image.fromarray
уже учитывает это. То есть arr2im.size == im.size
и arr2im.mode == im.mode
в приведенном выше примере.
Мы должны позаботиться о формате данных HxWxC при обработке преобразованных числовых массивов, например, выполнить преобразование im2arr = np.rollaxis(im2arr, 2, 0)
или im2arr = np.transpose(im2arr, (2, 0, 1))
в Формат CxHxW.
Ответ 4
Вам нужно преобразовать ваше изображение в массив numpy следующим образом:
import numpy
import PIL
img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img)
Ответ 5
Пример, который я использовал сегодня:
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)
Ответ 6
Если ваше изображение хранится в формате Blob (то есть в базе данных), вы можете использовать ту же технику, которая была объяснена Биллалом Бегераджем, чтобы преобразовать ваше изображение из BLOB-объектов в байтовый массив.
В моем случае мне понадобились мои изображения, которые хранятся в столбце 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])
Ответ 7
def imshow(img):
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
Вы можете преобразовать изображение в numpy, проанализировав изображение в функции numpy() после выделения функций (ненормализация)