TL;DR cv3 - обёртка над opencv-python, которая ускоряет написание кода, не сужая функциональность Привет, Хабр! Хочу поделиться написанным мною фреймворком на Python, который упрощает работу с OpenCV и делает его более питоничным. Погнали! Демонстрация возможностей Мотивация Знакомьтесь, cv3 Особенности cv3 cv2 vs cv3 Обзор функций Сравнение с аналогами  Подводим итоги Источники Сразу начну с демонстрации возможностей на примере реальных задач, которые встают перед исследователями компьютерного зрения, дата инженерами в области CV, разработчиками в области обработки изображений и другими специалистами. Подробнее про YOLOv5 В данном коде происходит чтение изображения, получение предсказаний от модели и отрисовка детекций. В конце создаётся окно, на котором отображается изображение с детекциями. Пример кода для переноса изображений из одной папки в другую с изменением размера изображений. Здесь обходятся все jpeg изображения из папки images, приводятся к размеру 256x256 и сохраняются под тем же именем в папке images256. Код для отрисовки детекций лиц и ландмарков, полученных от dlib. Подробнее про dlib В коде считывается изображение, на нём запускается детектор лиц, и для каждой детекции определяются ключевые точки лица. Полученные детекции наносятся на изображение, после чего изображение выводится на экран. В коде создаётся 4 окна, далее происходит итерирование по видеопотоку с веб-камеры. Кадры обрабатываются (цвета конвертируются в gray/hsv; применение трешолда) и отправляются на вывод в соответствующие окна. Если вводится ‘q’, то окна закрываются и программа завершается. Пример кода, с помощью которого из цветного видео можно получить черно-белое. В коде создаются поток записи и чтения видео. Далее происходит итерирование по видеопотоку чтения, пока он не завершится. На каждой итерации кадр преобразуется из RGB в GRAY формат и отправляется в выходной поток. Ниже приведён код для создания анимации из изображения при помощи преобразований масштабирования и вращения. В коде считывается изображение и создаётся поток записи видео. Далее к изображению последовательно применяются трансформации, и результат отправляется в выходной поток. В большинстве проектов по обработке изображений и компьютерному зрению используется библиотека OpenCV, написанная на C++. Данная библиотека хорошо зарекомендовала себя и пока не уступает аналогам, благодаря огромному числу реализованных алгоритмов компьютерного зрения и своей гибкости. У OpenCV есть интерфейс, написанный на Python: opencv-python или cv2. У него есть ряд преимуществ:  Высокая скорость работы алгоритмов благодаря тому, что cv2 - интерфейс к OpenCV Работа с изображениями осуществляется через numpy матрицы, что даёт возможность пользоваться методами numpy Большой функционал: возможность использования всех алгоритмов, реализованных в OpenCV, с минимальными усилиями Однако в ней есть ряд недостатков, связанных с интерфейсом, с которыми сообщество ничего не делает и, судя по всему, не собирается делать. Приведу их: Изображения считываются и записываются в BGR формате. Это особенность присуща только OpenCV, в других библиотеках работа происходит в RGB формате. Из-за этого возникают конфликты при использовании разных библиотек в одном проекте (например, связка cv2+matplotlib). Данная фича создаёт путанницу, особенно у новичков, и отвлекает от решения основной задачи. Типичная проблема, возникающая на практике: аватары вместо людей. Ошибки не обработаны должным образом. Например при чтении несуществующего файла, не вылетают ошибки, а при проблеме во время записи изображения в файл возвращается безобидное False. Зачастую очень сложно понять, с чем связана та или иная ошибка. К примеру, ошибка TypeError: Expected cv::UMat for argument, периодически возникающая при рисовании фигур Жёсткая привязка функций OpenCV к матрицам типа uint8. В целом, это хорошее решение, так как каждый пиксель должен принимать значение от 0 до 255, но из ошибок не всегда можно понять, что проблема в типе матрицы Очень много лишнего кода, который приходится каждый раз копировать со stackoverflow (если у вас не феноменальная память на странные вещи). Например, для вращения изображения в cv2 необходимо сперва получить матрицу вращения, после чего применить её к изображению. Много обязательных аргументов функций, без которых можно обойтись. Например, обязательное указание цвета линий при рисовании прямоугольника или несколько различных параметров при нанесении текста. Или при записи видео в файл необходимо передавать разрешение кадров, хотя данную информацию можно извлечь из первого записанного кадра. И в случае неправильной передачи этого аргумента, видео просто-напросто не запишется без каких-либо ошибок. Огромное множество флагов, которые нельзя уместить в голове и, соответственно, приходится гуглить каждый раз. Примеры: cv2.cv.CV_CAP_PROP_FRAME_COUNT для получения количество кадров в видео, cv2.INTER_LINEAR для указания типа интерполяции и т. д. Разные названия параметров функций, которые отвечают за одно и то же. Например, в cv2.copyMakeBorder указываются параметры borderType и value для задания границ, а в cv2.warpAffine за это отвечают borderMode и borderValue. Ещё пример: для указания типа интерполяции в cv2.resize используется параметр interpolation, а в cv2.warpAffine - flags Я уже много лет работаю в области компьютерного зрения и использую cv2 в своих проектах. И каждый раз работа с этой библиотекой доставляет дискомфорт, хоть и достойного аналога у неё нет. Поэтому в один момент я решил написать обёртку над cv2, чтобы ускорить работу с этой библиотекой - cv3. cv3 - это более питоничный интерфейс к OpenCV. Он упрощает работу с этой библиотекой, расширяет его синтаксические возможности, а также ускоряет исследования в области компьютерного зрения и выполнение задач по обработке изображений, при этом сохраняя гибкость и функциональность OpenCV. Цель проекта: сделать OpenCV более питоничным и удобным в использовании, понизить порог входа в область компьютерного зрения.  Задача cv3: абстрагироваться от лишнего кода (лишних аргументов и преобразований типов), при этом сохранив всю мощь и весь функционал этой библиотеки. Таким образом, фокус идёт на решении более важных задач компьютерного зрения, чем переписывание ненужного кода, копирование его со stackoverflow и его дебаг.  Первоначальная идея была контрибьютить в репозиторий cv2, но я быстро от неё отказался. И вот почему: в cv3 очень много принципиальных вещей, которые не соотносятся с OpenCV. Это и внутренние состояния, и добавление исключений, и новые сущности, и синонимичные названия функций, и дополнительные методы и так далее. Так что cv3 разрабатывался как интерфейс к cv2. Отношения cv3, opencv-python и OpenCV можно провизуализировать следующим образом: К главным фичам cv3 можно отнести: Избавление от жёсткой типизации Поддержка относительных координат Использование однотипных интерфейсов для работы с потоками. К примеру, VideoCapture, VideoWriter, Window поддерживают открытие через контекстный менеджер и могут быть закрыты через метод .close() Выбрасывание понятных исключений при возникновении проблем. Например, при чтении несуществующего файла или записи в видеофайл кадра с неправильным разрешением. Использование snake_case, вместо CamelCase, в соответствии со стандартом Python. К примеру, вместо cvtColor предлагается использовать cvt_color Далее расскажу подробнее про особенности. Чтение и запись изображений/видео, цвет в RGB формате. Это обеспечивается хранением внутреннего состояния cv3.opt.RGB=True. Данное состояние можно переключить через cv3.opt.set_bgr() Автокаст изображений. Если в функцию передаётся изображение в неправильном формате, то оно приводится к np.uint8, и появляется предупреждение. Также поддерживается изображение в формате PIL Поддержка относительных координат. Возможность делать обрезку изображения (cv3.crop), паддинг (cv3.pad), ресайз (cv3.resize), отрисовку фигур в относительных координатах. Параметр rel=True означает, что переданы относительные координаты; rel=False - целые координаты. По умолчанию rel=None, в этом случае координаты считаются относительными, если они имеют тип float и находятся в диапазоне от 0 до 1. Добавление множества функций на основе методов cv2, которые часто используются на практике: cv3.transform (вращение и масштабирование изображения) cv3.rgb2gray (перевод rgb изображения в gray формат), cv3.hline (рисование горизонтальной линии) и т. д. Поддержка нескольких режимов (mode) отрисовки прямоугольника (cv3.rectangle) или обрезки изображения (cv3.crop): “xyxy” (по умолчанию) - формат (x0, y0, x1, y1). Возможны 4 варианта, например, (xmin, ymin, xmax, ymax) “xywh” - формат (x0, y0, width, height) “ccwh” - формат (x-center, y-center, width, height) “yyxx” - формат (y0, y1, x0, x1) cv3.imread вторым параметром может принимать flag: либо cv2 флаг, либо строка (‘color’, ‘gray’, ‘alpha’) Поддержка pathlib при чтении/записи изображений/видео Автоматическое создание папок при записи изображения или видео при необходимости (при передаче параметра mkdir=True) Добавление класса Window. Он позволяет удобным образом управлять окнами, в которых отображаются изображения/видео. Также содержит в себе счётчик окон, благодаря чему необязательно задавать название окон при инициализации. Инициализация видеопотоков через cv3.Video. Для чтения из source используется cv3.Video(source), для записи в файл - cv3.Video(filename, ‘w’). Под капотом классы: cv3.VideoCapture и cv3.VideoWriter соответственно, которые расширяют возможности одноименных классов cv2. Например, поддерживается контекстный менеджер (видеопотоки автоматически закрываются при выходе из блока with..as). cap.read() возвращает кадр либо выбрасывает исключение: OSError (ошибка чтения) или StopIteration (видео закончено) Итерирования по видеопотоку чтения: реализованы методы __iter__ и __next__. Благодаря этому можно пользоваться циклом for. Свойства видео хранятся в полях объекта: frame_cnt (количество кадров, также возвращается от __len__), fps, width, height. Для получения текущего номера кадра используется обновляемое свойство cap.now. Перемотка на n-ый кадр осуществляется через cap.rewind(n). А для получение n-ого кадра через индексацию: cap[n]. Не надо передавать размеры кадров при инициализации cv3.VideoWriter: инициализация “родительского” cv2.VideoWriter происходит при записи первого кадра (здесь же определяется разрешение видео) Нет необходимости передавать fps и fourcc: используются значения по умолчанию: cv3.opt.FPS и cv3.opt.FOURCC. Параметр fourcc можно передавать как строку или как  результат вызова cv2.VideoWriter_fourcc Выбрасывание исключения OSError в случае, если видео не может быть записано Валидация размеров записываемых кадров: в случае, если размеры не совпадают, то выбрасывается исключение.  При отрисовке можно передать параметр copy=True - тогда функция вернёт копию изображения с нанесённой фигурой При отрисовке фигуры нет необходимости указывать её цвет: используется заданное значение cv3.opt.COLOR, которое можно переопределить. Помимо этого, можно переопределить толщину линий фигуры через cv3.opt.THICKNESS При отрисовке можно передавать дополнительные параметры color (цвет), t (толщина), line_type (тип линии) Параметр color. Поддерживаются именованные цвета и относительные значения цветов. Если cv3.opt.RGB=True, то цвет ожидается в формате RGB, а иначе BGR. Если в качестве параметра цвета передана строка и cv3.opt.RGB=False, то соответствующий цвет разворачивается (RGB->BGR). Поддерживаются следующие типы значений параметра color: int - целое число от 0 до 255 float - целое число от 0 до 255 либо относительное от 0 до 1 np.array/list/tuple - массив из 3 чисел, целых или относительных str - название цвета. Доступные цвета доступны в cv3.COLORS Параметр line_type. Ожидается либо cv2 флаг, либо строка: 'filled', 'line_4', 'line_8', 'line_aa' При нанесении текста достаточно указать только строку текста. По умолчанию, текст будет начинаться с центра изображения (x=0.5, y=0.5). Можно указывать тип шрифта через параметр font (cv2 флаг либо строка: 'simplex', 'plain', 'duplex', 'complex', 'triplex', 'complex_small', 'script_simplex', 'script_complex', 'italic'). Параметр scale отвечает за масштаб текста, flip - за разворот текста (принимает True/False) За интерполяцию при применении трансформаций отвечает параметр inter. Он есть в функциях cv3.transform, cv3.rotate, cv3.scale, cv3.resize и т.п. Параметр inter может принимать либо cv2 флаг, либо строку. Возможные строковые значения: 'nearest', 'linear', 'area', 'cubic', 'lanczos4' За границы отвечают параметры border (тип границы) и value. Они есть в функциях  cv3.transform, cv3.rotate, cv3.scale, cv3.shift, cv3.pad и т.п.  В качестве border передаётся либо cv2 флаг, либо строка: 'constant', 'replicate', 'reflect', 'wrap', 'default'. value используется только когда тип границы ‘constant’. Принимает value такие же типы значений, как параметр color в функциях рисования cv3.crop позволяет обрезать изображение, даже если координаты выходят за его пределы Приведу сравнение кода, написанного на cv2 и cv3, для решения стандартных задач. cv2 cv3 cv2 cv3 cv2 cv3 Задача cv2 cv3 Чтение и запись изображений 3.21 ms ± 129 µs 3.9 ms ± 76.3 µs Рисование 1.47 ms ± 13 µs 1.59 ms ± 16.1 µs Чтение и запись видео 88.4 ms ± 3.33 ms 103 ms ± 1.53 ms Как и ожидалось, код на cv3 отрабатывает медленнее cv2, так как использует дополнительные обёртки и интерфейсы. Однако с точки зрения Python такое замедление незначительное, и в результате получается понятный код. Такой код пишется быстрее и менее подвержен ошибкам. Таким образом, cv3 позволяет снизить время на разработку и багфикс, сделать код понятнее, но при этом слегка снижает производительность. Сперва нужно установить библиотеку. Делается это следующим образом: Для импортирования её в Python достаточно прописать: Ознакомиться с функциями и позапускать код можно в гугл колабе по ссылке Репозиторий github здесь Примеры из статьи можно найти здесь По всем функциям были проведены юнит-тесты, протестировано на разных платформах, версиях python и opencv-python. Рассмотрим аналоги с cv3. При рассмотрении будем считать, что cv3 реализует все алгоритмы из OpenCV, и сравнивать по большей мере будем юзабилити scikit-image. В данной библиотеке реализовано огромное число алгоритмов компьютерного зрения, однако она всё-равно уступает OpenCV по этому критерию. Также не поддерживается работа с видео. PIL. Предназначена для работы с изображениями. Реализует много аналогичных функций из OpenCV. Из недостатков: работа с изображениями происходит через сущность Image, а не numpy матрицу; также не поддерживается работа с видео. torchvision. Это библиотека, являющаяся дополнением к библиотеке глубокого обучения PyTorch. Она реализует большое число алгоритмов для аугментации изображений. Также здесь поддерживается работа с видео. Из недостатков то, что функции ожидают в качестве входов PIL.Image либо torch.Tensor, Помимо этого, нет гибкости при работе с видео из-за того, что библиотека завязана на задачи, связанные с глубоким обучением. albumentations. Это библиотека, написанная на OpenCV, которая предназначена для аугментации изображений. В ней реализовано огромное множество функций для преобразований изображений. К плюсам можно отнести то, что поддерживаются numpy матрицы в качестве входов. Однако за счёт того, что библиотека заточена на аугментации изображений, в ней используется специфичный интерфейс, который избыточен для задач по обработке изображений. Здесь также не реализован функционал для работы с видео потоками. imutils. Это серия удобных и полезных функций, написанных на cv2, для работы с изображениями. При этом, это дополнение к cv2, а не отдельная библиотека. Также там есть очень интересная функция: opencv2matplotlib, разворачивающая каналы из BGR в RGB, которой вряд ли кто-либо пользуется :) SimpleCV. Также как и cv3, данная библиотека, нацелена на простоту в использовании при работе с изображениями. Однако она завязана на внутренние сущности, и в ней ограниченный функционал, по сравнению с OpenCV. Из-за этого возникает проблема негибкости библиотеки. Помимо этого, поддержка SimpleCV прекратилась в 2021 году, тогда как OpenCV обновляется по сей день. SimpleCV можно назвать хорошим инструментом для изучения компьютерного зрения, но для использования в реальных задачах он непригоден.  Таким образом, OpenCV можно считать универсальной библиотекой в области компьютерного зрения, а cv3 - удобным интерфейсом к ней, у которого на данный момент не имеется аналогов.  В данной статье был представлен новый фреймворк для обработки изображений - cv3, который аналогично cv2 реализует функции OpenCV, но делает код более питоничным. Были приведены возможности cv3, а также сравнение с аналогами и cv2 по производительности и юзабилити. Как и ожидалось, cv3 уступает cv2 по производительности, но при этом обходит его по скорости написания кода, readability; снижает количество кода и число ошибок. Таким образом, cv3 больше подходит для исследовательских задач по CV и написания скриптов по обработке и переносу изображений. В случае же, когда скорость исполнения кода важна, например, в продакшн условиях, то следует использовать cv2. Пока реализованы основные функции, по всем ним проведены тесты. Проект планируется развивать, постепенно будут появляться новые функции. Предстоит ещё много работы, и один я с ней точно не справлюсь. Задач много: написание и поддержка документации в readthedocs, размещение проекта на PyPi, переписывание других функций OpenCV на более удобный лад и т.д.  Надеюсь данный проект будет многим полезен и сообщество поддержит данную инициативу. Контрибутьте! Вопросы и предложения пишите в чат Telegram либо создавайте issue в репозитории pycv - github  OpenCV  YOLOv5 scikit-image PIL torchvision albumentations  simpleCV matplotlib dlib