Использование метода Image.point () в PIL для управления пиксельными данными

Я использую библиотеку изображений Python для раскрашивания черно-белого изображения с помощью таблицы поиска, которая определяет отношения цвета. Таблица поиска – это всего лишь 256-элементный список кортежей RGB:

>>> len(colors) 256 >>> colors[0] (255, 237, 237) >>> colors[127] (50, 196, 33) >>> 

Моя первая версия использовала getpixel() и putpixel() :

  for x in range(w): for y in range(h): pix = img.getpixel((x,y)) img.putpixel((x,y), colors[pix[0]]) 

Это было ужасно медленно. Отчет о profile указывал на методы putpixel и getpixel в качестве виновников. Небольшое исследование (т . putpixel Чтение документов), и я нахожу « Обратите внимание, что этот метод относительно медленный». Re: putpixel . ( фактическое время исполнения : 53 с в putpixel и 50s getpixel для изображения 1024×1024)

Основываясь на предположении в документах, я использовал im.load() и прямой доступ к пикселям:

  pixels = img.load() for x in range(w): for y in range(h): pix = pixels[x, y] pixels[x, y] = colors[pix[0]] 

Обработка ускоряется на порядок, но все еще медленно: около 3,5 секунд для обработки изображения 1024×1024.

Более тщательное изучение документов PIL, похоже, указывает на то, что Image.point() предназначен именно для этой цели:

im.point(table) => изображение

im.point(function) => изображение

Возвращает копию изображения, в котором каждый пиксель был сопоставлен в данной таблице. Таблица должна содержать 256 значений для диапазона в изображении. Если вместо этого используется функция, она должна принимать один аргумент. Функция вызывается один раз для каждого возможного значения пикселя, и результирующая таблица применяется ко всем полосам изображения.

Я потратил некоторое время на хакерство с интерфейсом, но, похоже, не все правильно. Простите мое невежество, но документы PIL коротки, и у меня мало опыта обработки изображений. Я немного поработал с поиском, и я привел несколько примеров, но ничто из того, что сделало использование «щелчком» для меня. Итак, наконец, мои вопросы:

  • Является ли Image.point() правильным инструментом для этой работы?
  • Какой формат / структура выполняет Image.point() ожидании таблицы?
  • Может ли кто-то провести пример реализации? На каждой итерации, которую я пробовал до сих пор, оказалось прямое черное изображение.

2 Solutions collect form web for “Использование метода Image.point () в PIL для управления пиксельными данными”

Является ли Image.point () правильным инструментом для этой работы?

Да, действительно, Image.point() идеально подходит для этой работы

Какой формат / структура выполняет Image.point () в ожидании таблицы?

Вы должны сгладить список, чтобы вместо [(12, 140, 10), (10, 100, 200), ...] использовать:

 [12, 140, 10, 10, 100, 200, ...] 

Вот простой пример, который я только что попробовал:

 im = im.point(range(256, 0, -1) * 3) 

alt textalt text

И, кстати, если вам нужно больше контролировать цвета, и вы чувствуете, что Image.point не для вас, вы также можете использовать Image.getdata и Image.putdata чтобы менять цвета быстрее, чем load и putpixel . Это медленнее, чем Image.point .

Image.getdata дает вам список всех пикселей, модифицирует их и записывает их с помощью Image.putdata . Это так просто. Но сначала попробуйте сделать это с помощью Image.point .


РЕДАКТИРОВАТЬ

Я ошиблась в первом объяснении, я сейчас правильно объясню:

Фактически таблица цветов выглядит так

 [0, 1, 2, 3, 4, 5, ...255, 0, 1, 2, 3, ....255, 0, 1, 2, 3, ...255] 

Каждый диапазон находится рядом друг с другом. Чтобы изменить цвет (0, 0, 0) на (10, 100, 10), он должен выглядеть следующим образом:

 [10, 1, 2, 3, 4, 5, ...255, 100, 1, 2, 3, ....255, 10, 1, 2, 3, ...255] 

Чтобы преобразовать список цветов в правильный формат, попробуйте следующее:

 table = sum(zip(*colors), ()) 

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

Я думаю, что было бы более типично point на поэтапную основу (например, снятую непосредственно из учебника PIL):

 # split the image into individual bands source = im.split() R, G, B = 0, 1, 2 # select regions where red is less than 100 mask = source[R].point(lambda i: i < 100 and 255) # process the green band out = source[G].point(lambda i: i * 0.7) # paste the processed band back, but only where red was < 100 source[G].paste(out, None, mask) # build a new multiband image im = Image.merge(im.mode, source) 
  • используя pyodbc на ubuntu для вставки поля изображения на SQL Server
  • Python, PIL; Текст в изображение и шрифты
  • matplotlib - хранить изображение в переменной
  • изменить размер массива 2D numpy, исключая NaN
  • Автоматическое обрезание изображения с помощью python / PIL
  • Python ImageIO Gif устанавливает задержку между кадрами
  • Искра с использованием PySpark
  • Построить Pygame с поддержкой полного изображения?
  • Python - лучший язык программирования в мире.