ما هي أسرع طريقة لرسم صورة من قيم البكسل المنفصلة في بايثون؟
-
10-07-2019 - |
سؤال
أرغب في رسم صورة بناءً على قيم البكسل المحسوبة، كوسيلة لتصور بعض البيانات.في الأساس، أود أن آخذ مصفوفة ثنائية الأبعاد مكونة من ثلاثة توائم ملونة وأقوم بتصييرها.
لاحظ أن هذه ليست معالجة للصور، حيث أنني لا أقوم بتحويل صورة موجودة ولا أقوم بأي نوع من تحويلات الصورة بأكملها، كما أنها ليست رسومات متجهة لأنه لا يوجد هيكل محدد مسبقًا للصورة التي أعرضها- من المحتمل أن أقوم بإنتاج نقاط غير متبلورة من الألوان بمقدار بكسل واحد في كل مرة.
أحتاج إلى تقديم صور بحجم 1 كيلو × 1 كيلو بكسل في الوقت الحالي، ولكن شيئًا قابلاً للتطوير سيكون مفيدًا.التنسيق المستهدف النهائي هو PNG أو أي تنسيق آخر بدون فقدان البيانات.
أنا أستخدم PIL في الوقت الحالي عبر draw.point الخاص بـ ImageDraw، وكنت أتساءل، نظرًا للميزات المحددة جدًا والأساسية نسبيًا التي أحتاجها، هل هناك أي مكتبة متاحة أسرع؟
المحلول
إذا كان لديك numpy
وscipy
متوفرة (وإذا كنت التلاعب صفائف كبيرة في بيثون، أود أن أوصي لهم)، ثم في وظيفة scipy.misc.pilutil.toimage
هو مفيد للغاية.
وهناك مثال بسيط:
import numpy as np
import scipy.misc as smp
# Create a 1024x1024x3 array of 8 bit unsigned integers
data = np.zeros( (1024,1024,3), dtype=np.uint8 )
data[512,512] = [254,0,0] # Makes the middle pixel red
data[512,513] = [0,0,255] # Makes the next pixel blue
img = smp.toimage( data ) # Create a PIL image
img.show() # View in default viewer
والشيء الجميل هو toimage
تتواءم مع أنواع مختلفة من البيانات بشكل جيد للغاية، لذلك مجموعة 2D من أرقام الفاصلة العائمة يحصل على تحويلها بشكل معقول إلى تدرج الرمادي وغيرها.
ويمكنك تنزيل numpy
وscipy
من هنا . أو باستخدام النقطة:
pip install numpy scipy
نصائح أخرى
import Image
im= Image.new('RGB', (1024, 1024))
im.putdata([(255,0,0), (0,255,0), (0,0,255)])
im.save('test.png')
ويضع بكسل الأحمر والأخضر والأزرق في أعلى يسار الصورة.
وim.fromstring()
أسرع إذا كنت لا تزال تفضل التعامل مع القيم بايت.
متطلبات
وعلى سبيل المثال، تثبيت نمباي و <لأ href = "HTTP: //pillow.readthedocs .io / EN / 3.1.x / installation.html "يختلط =" نوفولو noreferrer "> وسادة .
مثال
والهدف هو تمثيل أولا الصورة التي ترغب في إنشاء باعتبارها صفائف مجموعة من مجموعات من 3 أرقام (RGB) - استخدام نمباي في <لأ href = "https://docs.scipy.org/doc/numpy-1.13 0.0 / إشارة / الناتج / numpy.array.html "يختلط =" نوفولو noreferrer "> array()
أو لأداء والبساطة:
import numpy
data = numpy.zeros((1024, 1024, 3), dtype=numpy.uint8)
والآن، تعيين قيم RGB 3 بكسل الوسطى "إلى اللون الأحمر، والأخضر، والأزرق:
data[512, 511] = [255, 0, 0]
data[512, 512] = [0, 255, 0]
data[512, 513] = [0, 0, 255]
وبعد ذلك، استخدم وسادة ل Image.fromarray()
لتوليد صورة من مجموعة:
from PIL import Image
image = Image.fromarray(data)
والآن، "عرض" صورة (على OS X، وهذا سيفتح على أنها ملف مؤقت في معاينة):
image.show()
ملاحظة
وكان مصدر إلهام هذه الإجابة من طرف الجواب BADCODE، الذي كان أيضا من تاريخ الاستخدام ومختلفة جدا لمجرد تحديث دون إعادة كتابة تماما.
وهناك نهج مختلف هو استخدام Pyxel أو التنفيذ مفتوحة المصدر من <لأ href = "HTTPS : //github.com/nesbox/TIC-80 "يختلط =" نوفولو noreferrer "> وAPI TIC-80 في Python3 (TIC-80 هو المصدر المفتوح PICO-8)
.وهنا التطبيق الكامل الذي يرسم فقط بكسل واحد أصفر على خلفية سوداء:
import pyxel
def update():
"""This function just maps the Q key to `pyxel.quit`,
which works just like `sys.exit`."""
if pyxel.btnp(pyxel.KEY_Q): pyxel.quit()
def draw():
"""This function clears the screen and draws a single
pixel, whenever the buffer needs updating. Note that
colors are specified as palette indexes (0-15)."""
pyxel.cls(0) # clear screen (color)
pyxel.pix(10, 10, 10) # blit a pixel (x, y, color)
pyxel.init(160, 120) # initilize gui (width, height)
pyxel.run(update, draw) # run the game (*callbacks)
ملاحظة : ل. المكتبة يسمح فقط لمدة تصل إلى ستة عشر لونا، ولكن يمكنك تغيير الألوان التي، وربما يمكنك الحصول عليه لدعم أكثر من دون الكثير من العمل
أعتقد أنك تستخدم PIL لإنشاء ملف صورة على القرص، ثم تقوم بتحميله لاحقًا باستخدام برنامج قارئ الصور.
يجب أن تحصل على تحسن بسيط في السرعة من خلال عرض الصورة مباشرة في الذاكرة (ستوفر تكلفة كتابة الصورة على القرص ثم إعادة تحميلها).إلقاء نظرة على هذا الموضوع https://stackoverflow.com/questions/326300/python-best-library-for-drawing لمعرفة كيفية تقديم تلك الصورة باستخدام وحدات بايثون المختلفة.
سأحاول شخصيًا استخدام wxpython و dc.DrawBitmap وظيفة.إذا كنت تستخدم مثل هذه الوحدة بدلاً من قارئ الصور الخارجي، فستحصل على العديد من الفوائد:
- سرعة
- ستتمكن من إنشاء واجهة مستخدم تفاعلية تحتوي على أزرار للمعلمات.
- ستكون قادرًا على برمجة وظيفة Zoomin وZoomout بسهولة
- ستكون قادرًا على رسم الصورة أثناء حسابها، وهو ما قد يكون مفيدًا جدًا إذا استغرق الحساب الكثير من الوقت