Какой самый быстрый способ нарисовать изображение из дискретных значений пикселей в Python? - PullRequest
33 голосов
/ 12 января 2009

Я хочу нарисовать изображение на основе вычисленных значений пикселей, чтобы визуализировать некоторые данные. По сути, я хочу взять двумерную матрицу цветовых триплетов и визуализировать ее.

Обратите внимание, что это не обработка изображения, поскольку я не преобразую существующее изображение и не делаю никаких преобразований целого изображения, а также не являюсь векторной графикой, поскольку для изображения I нет предварительно определенной структуры. ' m рендеринга - я, вероятно, собираюсь производить цветные аморфные капли по одному пикселю за раз.

Мне нужно визуализировать изображения размером около 1kx1k пикселей, но было бы полезно что-то масштабируемое. Конечный целевой формат - PNG или любой другой формат без потерь.

В настоящее время я использую PIL через draw.point ImageDraw, и мне было интересно, учитывая, какие специфические и относительно базовые функции мне нужны, есть ли более быстрая доступная библиотека?

Ответы [ 5 ]

33 голосов
/ 12 января 2009

Если у вас есть numpy и scipy (и если вы манипулируете большими массивами в Python, я бы порекомендовал их), то функция 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 отлично справляется с различными типами данных, поэтому двумерный массив чисел с плавающей точкой разумно преобразуется в оттенки серого и т. Д.

Вы можете скачать numpy и scipy с здесь . Или используя пункт:

pip install numpy scipy
16 голосов
/ 12 января 2009
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() быстрее, если вы предпочитаете иметь дело со значениями байтов.

2 голосов
/ 31 июля 2018

Другой подход заключается в использовании Pyxel , реализации с открытым исходным кодом 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)

Примечание : библиотека допускает только до шестнадцати цветов, но вы можете изменить, какие цвета, и вы могли бы получить ее для поддержки большего количества без слишком большой работы.

2 голосов
/ 24 января 2018

Требования

Для этого примера установите Numpy и Подушка .

Пример

Цель состоит в том, чтобы сначала представить изображение, которое вы хотите создать, в виде массива массивов наборов из 3 (RGB) чисел - используйте Numpy's 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]

Затем используйте Pillow's Image.fromarray(), чтобы сгенерировать изображение из массива:

from PIL import Image

image = Image.fromarray(data)

Теперь «покажите» изображение (в OS X это откроет его как временный файл в Preview):

image.show()

Примечание

Этот ответ был вдохновлен ответом BADCODE, который слишком устарел для использования и слишком отличается от простого обновления без полной перезаписи.

1 голос
/ 12 января 2009

Я думаю, что вы используете PIL для создания файла образа на диске, а затем загружаете его с помощью программы чтения изображений.

Вы должны получить небольшое улучшение скорости, визуализируя непосредственно изображение в памяти (вы сэкономите стоимость записи изображения на диск и последующей его загрузки). Посмотрите на эту ветку https://stackoverflow.com/questions/326300/python-best-library-for-drawing о том, как визуализировать это изображение с помощью различных модулей Python.

Я бы лично попробовал wxpython и функцию dc.DrawBitmap . Если вы используете такой модуль, а не внешний считыватель изображений, у вас будет много преимуществ:

  • Скорость
  • Вы сможете создать интерактивный пользовательский интерфейс с кнопками для параметров.
  • Вы сможете легко запрограммировать функции Zoomin и Zoomout
  • вы сможете построить изображение в процессе его вычисления, что может быть очень полезно, если вычисление занимает много времени
...