Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Работа с изображениями на Python в 2017 году

Работа с изображениями на Python в 2017 году

Александр Карпинский (lead backend developer @ uploadcare.com) @ Moscow Python Conf 2017
"Я работаю в компании Uploadcare и занимаюсь сервисом высокопроизводительной модификации изображений на лету. Некоторое время назад сделал ряд полезных изменений в популярной библиотеке для работы с изображениями Pillow. Параллельно развиваю свой форк Pillow-SIMD, нацеленный на максимальную производительность.
В докладе я расскажу, как наиболее эффективно можно решать задачи обработки изображений в современном Питоне. Какие есть инструменты, какие могут быть подводные камни. Поделюсь собственным опытом и наработками".
Видео: https://conf.python.ru/rabota-s-izobrazheniyami-na-python-v-2017-godu/

Moscow Python Meetup
PRO

October 20, 2017
Tweet

More Decks by Moscow Python Meetup

Other Decks in Programming

Transcript

  1. Работа с изображениями
    на Python в 2017 году
    Александр Карпинский, Uploadcare

    View Slide

  2. O себе
    Член команды Pillow.
    Автор Pillow-SIMD.
    1

    View Slide

  3. Чем занимаюсь
    Сервис обработки картинок на лету в Uploadcare.
    • Высокая производительность
    • Надежность
    • Масштабируемость
    • Построен на Pillow
    2

    View Slide

  4. Библиотеки
    3

    View Slide

  5. Pillow
    • Форк PIL (Python Imaging Library). 1995 год
    • Нативное расширение для Python
    • Версии Python: 2.7, 3.3+, pypy, pypy3
    Сайт: python-pillow.org
    4

    View Slide

  6. Pillow-SIMD
    • C мая 2016 года
    • Drop-in replacement for Pillow
    • Инструкции SSE4 (по умолчанию) и AVX2
    Сайт: github.com/uploadcare/pillow-simd
    5

    View Slide

  7. OpenCV
    • Расшифровывается Open Computer Vision. 2000 год
    • Биндинг на Python входит в комплект и очень популярен
    • Версии Python: 2.7, 3.4+, пока без pypy
    Сайт: opencv.org
    6

    View Slide

  8. VIPS
    • 1993 год, обогнала своё время
    • Биндинг pyvips поддерживается автором
    • Версии Python: 2.7, 3.3+, pypy, pypy3
    Сайт: jcupitt.github.io/libvips/
    7

    View Slide

  9. ImageMagick & GraphicsMagick
    • Очень популярная библиотека. 1990 год
    • Биндинг Wand использует ctypes, проект заброшен
    • Биндинг pgmagick использует Boost.Python, не работает в pypy
    Сайт: imagemagick.org, graphicsmagick.org
    8

    View Slide

  10. Производительность
    9

    View Slide

  11. 3
    3, 3
    Почему важно проверять результат
    from PIL import Image, ImageFilter.BoxBlur
    im.filter(ImageFilter.BoxBlur( ))
    ...
    import cv2
    cv2.blur(im, ksize=( ))
    ...
    01.
    02.
    03.
    01.
    02.
    03.
    10

    View Slide

  12. В чем проблема?
    cv2.GaussianBlur(im, (window, window), radius)
    radius = 3 58 ms radius = 30 880 ms
    11

    View Slide

  13. В чем проблема?
    im.filter(ImageFilter.GaussianBlur(radius))
    radius = 3 60 ms radius = 30 61 ms
    12

    View Slide

  14. Скорость ресайза в Pillow, Mpx/s
    13

    View Slide

  15. Скорость ресайза в Pillow, Mpx/s
    14

    View Slide

  16. Скорость ресайза в Pillow, Mpx/s
    15

    View Slide

  17. Скорость ресайза в Pillow, Mpx/s
    16

    View Slide

  18. Ускорение в Pillow-SIMD
    • Ресайз: от 4 до 7 раз
    • Размытие: 2,8 раз
    • Применение ядра 3x3 или 5x5: 11 раз
    • Умножение и деление на альфа-канал: в 4 и 10 раза
    • Альфа-композиция: 5 раз
    • Еще что-то по мелочи
    17

    View Slide

  19. Какой-то набор операций, Mpx/s
    Загрузка, поворот на 90°, уменьшение в 2,5 раза, размытие, запись в JPEG.
    18

    View Slide

  20. Какой-то набор операций, Mpx/s
    Если подождать и собрать самому.
    19

    View Slide

  21. Набор бенчмарков
    Страница с результатами
    https://python-pillow.org/pillow-perf/
    Фреймворк для тестирования
    https://github.com/python-pillow/pillow-perf
    20

    View Slide

  22. Параллельная работа
    21

    View Slide

  23. Метрики производительности
    • Реальное время выполнения одной операций
    Важно на десктопе.
    • Пропускная способность потока операций
    Становится более важным на сервере.
    22

    View Slide

  24. Способы параллельной работы
    1. На уровне приложения
    Реальное время выполнения не меняется.
    Пропускная способность растет пропорционально количеству ядер.
    23

    View Slide

  25. Способы параллельной работы
    2. На уровне графических операций
    Реальное время выполнения уменьшается.
    Пропускная способность растет далеко не линейно от количества ядер.
    24

    View Slide

  26. Способы параллельной работы
    3. На уровне команд процессора и данных (SIMD)
    Реальное время выполнения уменьшается.
    Пропускная способность растет.
    Win-win.
    25

    View Slide

  27. Как совместить параллельную работу
    SIMD
    внутри
    операций
    внутри
    приложения
    26

    View Slide

  28. Многопоточность
    Отпускают GIL
    Pillow, OpenCV, pyvips, Wand
    Не отпускает
    pgmagick
    27

    View Slide

  29. Правило N + 1
    Создавать для обработки не более N + 1 воркеров,
    где N — количество ядер или потоков процессора.
    Воркер — процесс или поток, занятый обработкой.
    28

    View Slide

  30. process_image
    Асинхронная работа
    Долгая работа процессора блокирует event loop,
    даже если библиотека отпускает GIL.
    @gen.coroutine
    def get(self, *args, **kwargs):
    im = (...)
    ...
    01.
    02.
    03.
    04.
    29

    View Slide

  31. 1
    yield
    Асинхронная работа
    @run_on_executor(executor=ThreadPoolExecutor( ))
    def process_image(self, ...):
    ...
    @gen.coroutine
    def get(self, *args, **kwargs):
    im = process_image(...)
    ...
    01.
    02.
    03.
    04.
    05.
    06.
    07.
    30

    View Slide

  32. Ввод/Вывод
    31

    View Slide

  33. %time
    1.2 ms
    Ленивая загрузка
    >>> from PIL import Image
    >>> im = Image.open('cover.jpg')
    Wall time:
    >>> im.mode, im.size
    ('RGB', (2152, 1345))
    01.
    02.
    03.
    04.
    05.
    32

    View Slide

  34. %time
    1.2 ms
    %time
    73.6 ms
    Ленивая загрузка
    >>> from PIL import Image
    >>> im = Image.open('cover.jpg')
    Wall time:
    >>> im.mode, im.size
    ('RGB', (2152, 1345))
    >>> im.load()
    Wall time:
    01.
    02.
    03.
    04.
    05.
    06.
    07.
    33

    View Slide

  35. IOError
    Режим битых картинок
    from PIL import Image
    Image.open('trucated.jpg').save('trucated.out.jpg')
    : image file is truncated (143 bytes not processed)
    01.
    02.
    03.
    34

    View Slide

  36. LOAD_TRUNCATED_IMAGES
    Режим битых картинок
    from PIL import Image, ImageFile
    ImageFile. = True
    Image.open('trucated.jpg').save('trucated.out.jpg')
    01.
    02.
    03.
    35

    View Slide

  37. Pillow VIPS OpenCV IM
    Количество кодеков 17 12+ 8 66
    Битые картинки ✅ ✅ ✅ ✅
    Ленивая загрузка ✅ ✅ ❌ ❌
    Чтение EXIF и ICC ✅ ✅ ❌ ✅
    Автоповорот EXIF ❌ ✅ ✅ ✅
    36

    View Slide

  38. Особенности OpenCV
    cv2.imread(filename)
    • Поворачивает JPEG-файлы в соответствии с EXIF
    • Игнорирует альфа-канал у PNG-файлов
    37

    View Slide

  39. cv2.IMREAD_UNCHANGED
    Особенности OpenCV
    cv2.imread(filename, flags= )
    • Оставляет альфа-канал у PNG-файлов
    • Перестает поворачивать JPEG-файлы
    38

    View Slide

  40. Почему так?
    • Мало кодеков
    • Нет ленивой загрузки
    • Нет доступа к EXIF и ICC
    • Странное флаги
    OpenCV не рассчитан на работу с непроверенными источниками.
    39

    View Slide

  41. Решение
    40

    View Slide

  42. numpy.array
    Решение
    Изображение в OpenCV — это массив numpy.
    import numpy
    from PIL import Image
    ...
    pillow_image = Image.open(filename)
    cv_image = (pillow_image)
    01.
    02.
    03.
    04.
    05.
    41

    View Slide

  43. Image.fromarray
    Решение
    import numpy
    from PIL import Image
    ...
    pillow_image = (cv_image, "RGB")
    pillow_image.save(filename)
    01.
    02.
    03.
    04.
    05.
    42

    View Slide

  44. Вопросы
    Презентация: homm.github.io/image-libs-2017/
    Написать: [email protected]
    43

    View Slide