Небезопасная обработка изображений в Python, такая как LockBits в C#

Можно ли выполнять небезопасную обработку изображений в Python?

Как и в случае с C#, я столкнулся с жесткой стеной при обработке пикселей в Python, поскольку метод getPixel из Image просто работает слишком медленно.

Можно ли получить прямой доступ к изображению в памяти, как это делает LockBits в С#? Это заставит мою программу работать намного быстрее.

Спасибо,

Отметка


person Mark Luong    schedule 15.12.2016    source источник


Ответы (1)


Ничего "небезопасного" в этом нет.

Как только вы поймете, как работает Python, станет очевидным, что вызов метода для получения информации о каждом пикселе будет медленным.

Прежде всего, хотя вы не даете никакой информации об этом, я предполагаю, что вы используете "Pillow" - библиотеку изображений Python (PIL), которая является наиболее известной библиотекой для обработки изображений с использованием Python. Поскольку это сторонний пакет, ничто не обязывает вас его использовать. (PIL имеет метод getpixel для изображений, но не getPixel)

Один простой способ получить все данные поддающимся манипулированию способом — создать объект bytearray данных изображения — учитывая изображение в переменной img, которую вы можете сделать:

data = bytearray(img.tobytes())  

Вот и все, у вас есть линейный доступ ко всем данным вашего изображения. Чтобы добраться до определенного пикселя, вам нужно получить ширину изображения, высоту и количество байтов на пиксель. Более поздний не является прямым атрибутом изображения в PIL, поэтому вы должны вычислить его с учетом mode изображения. Наиболее распространенными типами изображений являются RGB, RGBA и L.

Итак, если вы хотите написать прямоугольник в «x, y, width, size» на изображении, вы можете сделать это:

def rectangle(img, x,y, width, height):
    data = bytearray(img.tobytes())
    blank_data = (255,) * witdh * bpp
    bpp = 3 if data.mode == 'RGB' else 4 if data.mode == 'RGBA' else 1
    stride = img.width * bpp
    for i in range(y, y + height):
         data[i * stride + x * bpp: i * stride + (x + width) * bpp)] = blank_data
    return Image.frombytes(img.mode, (img.width, img.height), bytes(data))

То есть используется не сильно, а для простых манипуляций. Люди, которым необходимо применять фильтры и другие более сложные алгоритмы к изображениям с помощью Python, обычно получают доступ к изображению с помощью numpy — высокопроизводительного пакета обработки данных Python, который тесно связан с множеством других пакетов, которые имеют вещи, специфичные для изображений — обычно устанавливаются как scipy .

Итак, чтобы получить изображение в виде ndarray, которое уже выполняет все вышеуказанные преобразования координат -> байты за вас, вы можете использовать:

 import scipy.misc
 data = scipy.misc.imread(<filename>)

(Проверьте документы по адресу https://docs.scipy.org/doc/scipy/reference/ )

person jsbueno    schedule 15.12.2016