كيفية تحويل صورة PIL إلى صفيف Numpy؟
-
23-08-2019 - |
سؤال
حسنا، أنا بحاجة مع تحويل كائن صورة PIL ذهابا وإيابا إلى صفيف Numpy حتى أتمكن من القيام ببعض البكسل بشكل أسرع بواسطة تحويلات بكسل من Pil PixelAccess
سوف يسمح الكائن. لقد اكتشفت كيفية وضع معلومات البكسل في صفيف Numpy 3D مفيدة عن طريق:
pic = Image.open("foo.jpg")
pix = numpy.array(pic.getdata()).reshape(pic.size[0], pic.size[1], 3)
لكنني لا يبدو لي أن معرفة كيفية تحميلها مرة أخرى في كائن PIS بعد أن قمت بتحويلاتي رهيبة. أنا على علم putdata()
الطريقة، ولكن لا يمكن أن يبدو أن تحصل عليه أن تتصرف.
المحلول
أنت لا تقول كيف بالضبط 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
تتوقع سلسلة من tuples وأنت تعطيها صفيف numpy. هذه
>>> data = list(tuple(pixel) for pixel in pix)
>>> pic.putdata(data)
سوف تعمل ولكنها بطيئة جدا.
اعتبارا من pil 1.1.6، طريقة "مناسبة" للتحويل بين الصور وصفوفات Numpy هو ببساطة
>>> pix = numpy.array(pic)
على الرغم من أن الصفيف الناتج هو بتنسيق مختلف عنك (صفيف 3-D أو صفوف / أعمدة / RGB في هذه الحالة).
بعد ذلك، بعد إجراء تغييراتك على الصفيف، يجب أن تكون قادرا على القيام بذلك pic.putdata(pix)
أو إنشاء صورة جديدة مع Image.fromarray(pix)
.
نصائح أخرى
افتح I
كصفيف:
>>> I = numpy.asarray(PIL.Image.open('test.jpg'))
تفعل بعض الأشياء ل I
, ، ثم، قم بتحويله إلى صورة:
>>> im = PIL.Image.fromarray(numpy.uint8(I))
تصفية الصور Numpy مع FFT، Python
إذا كنت ترغب في القيام بذلك بشكل صريح لسبب ما، فهناك وظائف Pils2array () و Array2pil () باستخدام GetData () هذه الصفحة في الارتباط.zip.
أنا أستخدم وسادة 4.1.1 (خليفة PIL) في بيثون 3.5. التحويل بين الوسادة والحنمة واضحة.
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.size
و arr2im.mode == im.mode
في المثال أعلاه.
يجب أن نعتني بتنسيق بيانات HXWXC عند معالجة صفيفات Numpy المحولة، على سبيل المثال im2arr = np.rollaxis(im2arr, 2, 0)
أو im2arr = np.transpose(im2arr, (2, 0, 1))
في شكل cxhxw.
تحتاج إلى تحويل صورتك إلى صفيف Numpy بهذه الطريقة:
import numpy
import PIL
img = PIL.Image.open("foo.jpg").convert("L")
imgarr = numpy.array(img)
المثال، لقد استخدمت اليوم:
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)
إذا تم تخزين صورتك بتنسيق Blob (أي في قاعدة بيانات)، فيمكنك استخدام نفس التقنية الموضحة بواسطة Billal Begueradj لتحويل صورتك من النقط إلى صفيف بايت.
في حالتي، كنت بحاجة إلى صوري حيث يتم تخزينها في عمود Blob في جدول DB:
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])
def imshow(img):
img = img / 2 + 0.5 # unnormalize
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
يمكنك تحويل الصورة إلى Numpy عن طريق تحليل الصورة في وظيفة Numpy () بعد تسكيف الميزات (غير الحظرية)