Pull to refresh

Comments 14

Говорят что скорость библиотеки Pillow оставляет желать лучшего, все стараются переходить на OpenCV, особенно что касается применения различных фильтров и рисования.

Вроде если использовать Pillow-SIMD (https://github.com/uploadcare/pillow-simd), то иногда она обгоняет OpenCV на некоторых операциях (см. бенчмарки python-pillow.org/pillow-perf ).
Вообще, библиотеки каждая хорошая по своему, и есть ситуации когда и Pillow очень удобен. Думаю, преимущество OpenCV все же в большей мене обусловлено более богатом наборе инструментов, в т.ч. для многих задач комп. зрения.
мне всегда казалось, что OpenCV про работу с хардкорным компьютерным зрением, буду рад ошибиться

На C++ и правда OpenCV можно назвать хардкорным, но вот питоновский интерфейс очень приятный для использования, и совместим с numpy.

Кто говорит, покажите?

Код с Pillow не нашёл, из opencv там используются следующие возможности:


  • Загрузка/сохранение изображений
  • Ресайз
  • Некоторые операции в random_distort_image;
  • Кроме того есть нанесение текста и рисование прямоугольников, как я понял для дебага, то есть не самая критичная к производительности часть

Загрузка/сохранение изображений по большей части выполняется готовыми библиотеками вроде libjpeg-turbo или libwebp, тут вряд ли есть существенные различия. Отмечу лишь, что во время создания тикета пакет opencv-contrib-python, который есть в requirements.txt, собирался с обычной версией libjpeg, которая в несколько раз медленнее. Кроме того, после декодирования меняется порядок байт с BGR на RGB, что не добавляет скорости.


Про ресайз в OpenCV могу сказать, что он сломан для многих сочетаний размеров. Я к сожалению не понял из исходников, несколько сильный используется ресайз, в зависимости от этого результат OpenCV будет либо неверен и можно использовать супербыстрый фильтр nearest neighbor, либо результаты Pillow-SIMD с биллинейным фильтром будут не хуже.


В функции random_distort_image происходят интересные вещи и казалось бы тут уж Pillow нечем ответить. Но нет, все это укладывается в рамки операций, которые можно сделать с помощью 3D color LUT, что будет работать с константной скоростью для любого сочетания параметров. А конкретнее 50 мегапикселей/cек для Pillow и почти 400 мегапикселей/cек для Pillow-SIMD. Сама же функция random_distort_image работает со скоростью 41 мегапиксель/сек.


То есть по чистой производительности на ядро, Pillow, а тем более Pillow-SIMD для этих зада был бы быстрее. Единственное, с чем могли бы возникнуть проблемы — распараллеливание на несколько ядрер. Но тут я приверженец максимальной утилизации ресурсов, а для этого нужно запускать несколько задач параллельно, а не параллелить одну задачу внутри. А для этого в OpenCV тоже нет ничего встроенного.


Получается, зря говорят?

Спасибо за столь развернутый ответ, комментарий ценнее статьи в духе хабра!)) Призываю в тренд dkurt, может это будет тебе интересно))

Если что-то сломано в OpenCV — просим открыть баг репорт. Вообще, билинейная интерполяция это одна из священных войн всего CV где решается вопрос непортируемости и нет победителей и не будет. В том же DL нельзя так просто исправить даже забагованную реализацию, потому что все натренированные к тому моменту сети разойдутся. Взять пример How Tensorflow’s tf.image.resize stole 60 days of my life. А для параллелизма есть встроенный в OpenCV parallel_for о применении которого можно почитать в нашей статье https://m.habr.com/ru/company/intel/blog/489884/.

Если что-то сломано в OpenCV — просим открыть баг репорт. Вообще, билинейная интерполяция это одна из священных войн всего CV где решается вопрос непортируемости и нет победителей и не будет.

Так зачем просите писать, если знаете, что толку не будет? Вот например давно открытый ишью про ресайз.


Можете как раз взять пример из статьи на которую вы дали ссылку, там очень показательный пример. Только отресайзить его не в 4x4, а даже 3x3. Как это может превратиться в это?


       
оригинал, cv2.INTER_LINEAR, cv2.INTER_CUBIC


А должно получиться во всех случаях что-то вроде такого:


       
cv2.INTER_AREA, PIL.Image.LINEAR, PIL.Image.LANCZOS


И с NEAREST такие же проблемы, что в той статье:




для параллелизма есть встроенный в OpenCV parallel_for

Так я и говорю, что параллелизм на уровне одной операции всегда менее эффективен, чем распараллеливание нескольких операций, потому что есть а) накладные расходы на логику, запуск тредов, синхронизацию б) всегда найдется узкое место, которое не удастся распараллелить. Например код на питоне.

Сколько уже базовых туториалов по этой библиотеке. А сама библиотека богаче чем кажется на первый взгляд, да и активно развивается.
Например, в реальных проектах часто требуется поворачивать изображение согласно ориентации в EXIF (загрузил пользователь аватарку, которая снята на смартфон и бац, ориентация не верная).
Начиная с 6-й версии это делает вот так:
from PIL import ImageOps
image = ImageOps.exif_transpose(image)

и никакой больше возни. И таких «плюшек», про которых не говорят в подобных туториалах, очень много.
UFO just landed and posted this here

Но я же не пишу туториалы )

Использую opencv, хотя в некоторых случаях удобнее всё-таки использовать Pillow. Кстати, вот мой туториал по opencv: часть 1 и часть 2.

Sign up to leave a comment.

Articles