Каков самый быстрый способ нарисовать изображение из дискретных значений пикселей в Python?

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

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

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

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

Почему в Python есть оператор "pass"?
Почему в Python есть оператор "pass"?
Оператор pass в Python - это простая концепция, которую могут быстро освоить даже новички без опыта программирования.
Некоторые методы, о которых вы не знали, что они существуют в Python
Некоторые методы, о которых вы не знали, что они существуют в Python
Python - самый известный и самый простой в изучении язык в наши дни. Имея широкий спектр применения в области машинного обучения, Data Science,...
Основы Python Часть I
Основы Python Часть I
Вы когда-нибудь задумывались, почему в программах на Python вы видите приведенный ниже код?
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
LeetCode - 1579. Удаление максимального числа ребер для сохранения полной проходимости графа
Алиса и Боб имеют неориентированный граф из n узлов и трех типов ребер:
Оптимизация кода с помощью тернарного оператора Python
Оптимизация кода с помощью тернарного оператора Python
И последнее, что мы хотели бы показать вам, прежде чем двигаться дальше, это
Советы по эффективной веб-разработке с помощью Python
Советы по эффективной веб-разработке с помощью Python
Как веб-разработчик, Python может стать мощным инструментом для создания эффективных и масштабируемых веб-приложений.
43
0
60 996
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

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

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

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

  • скорость
  • вы сможете создать интерактивный пользовательский интерфейс с кнопками для параметров.
  • вы сможете легко запрограммировать функции Zoomin и Zoomout
  • вы сможете строить изображение по мере его вычисления, что может быть весьма полезно, если вычисление занимает много времени
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() еще быстрее, если вы предпочитаете иметь дело с байтовыми значениями.

В 2017 году первая строка: из PIL import Image

mountrix 10.07.2017 20:19
Ответ принят как подходящий

Если у вас есть 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 очень хорошо справляется с разными типами данных, поэтому 2D-массив чисел с плавающей запятой разумно преобразуется в оттенки серого и т. д.

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

pip install numpy scipy

Спасибо. Я уже довольно активно использую numpy :) Этот указатель как раз то, что мне нужно. Я мог бы сравнить скорости, если это станет узким местом, но пока это меня устраивает.

saffsd 14.01.2009 10:18

Если вы делаете это в научном контексте, вы также можете использовать «imshow» matplotlib.pyplot. он принимает в качестве аргументов цветовую карту и метод интерполяции и хорошо мне служил.

RodericDay 16.03.2013 18:43

toimage устарел: docs.scipy.org/doc/scipy/reference/generated/…

seddonym 01.11.2017 16:46

что делать, если у меня много пикселей ???? Около 5К, каким будет мой скрипт на Python для такого состояния ????

M. D. P 07.03.2019 07:34

@ M.D.P Если он уже в беззнаковом numpy, вы можете просто перейти к smp.toimage(). Если нет, просто используйте цикл for: см. Repl.it/@GezaK/PixelDraw.

Geza Kerecsenyi 30.05.2019 14:15

"module 'scipy.misc' не имеет атрибута 'toimage'" Вместо этого используйте непосредственно Image.fromarray Pillow. (источник)

Daddy32 06.11.2019 16:55

Требования

В этом примере установите Numpy и Подушка.

Пример

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

from PIL import Image

image = Image.fromarray(data)

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

image.show()

Примечание

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

Другой подход - использовать 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)

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

Вы можете использовать модуль turtle, если не хотите устанавливать внешние модули. Я создал несколько полезных функций:

  • setwindowsize( x,y ) - устанавливает размер окна x * y
  • drawpixel( x, y, (r,g,b), pixelsize) - рисует пиксель в координатах x: y с цветом (кортеж) RGB, с толщиной пикселя
  • showimage() - отображает изображение
import turtle

def setwindowsize(x=640, y=640):
    turtle.setup(x, y)
    turtle.setworldcoordinates(0,0,x,y)

def drawpixel(x, y, color, pixelsize = 1 ):
    turtle.tracer(0, 0)
    turtle.colormode(255)
    turtle.penup()
    turtle.setpos(x*pixelsize,y*pixelsize)
    turtle.color(color)
    turtle.pendown()
    turtle.begin_fill()
    for i in range(4):
        turtle.forward(pixelsize)
        turtle.right(90)
    turtle.end_fill()

def showimage():
    turtle.hideturtle()
    turtle.update()

Примеры:

Окно 200x200, 1 красный пиксель в центре

setwindowsize(200, 200)
drawpixel(100, 100, (255,0,0) )
showimage()

30x30 случайных цветов. Размер пикселя: 10

from random import *

setwindowsize(300,300)

for x in range(30):
    for y in range(30):
        color = (randint(0,255),randint(0,255),randint(0,255))
        drawpixel(x,y,color,10)
    
showimage()

Другие вопросы по теме