Как стать автором
Обновить
85.82
SimbirSoft
Лидер в разработке современных ИТ-решений на заказ

Как мы используем алгоритмы компьютерного зрения: обработка видео в мобильном браузере с помощью OpenCV.js

Время на прочтение 7 мин
Количество просмотров 3.4K
Для идентификации личности онлайн уже есть все возможности, но пока их применяют крайне редко. Пожалуй, одними из первых мы реализовали оптимальный сценарий для пользователя – зайти на сайт со смартфона, сфотографировать свои водительские права или паспорт и отправить данные в систему.

Рассмотрим, как алгоритмы компьютерного зрения помогают распознавать документы в видеопотоке прямо в браузерах мобильных устройств. В статье делимся опытом, как мы в SimbirSoft использовали для этого OpenCV.js, какие возможны сложности, как обеспечить быстродействие и получить «гладкий» UX без подтормаживания.




В чем заключалась задача


Бизнес-сценарий для разрабатываемого алгоритма следующий. Пользователь, зайдя на сайт с мобильного телефона, должен иметь возможность сфотографировать свои документы и направить их в систему для дальнейшей обработки. Это может быть частью процесса идентификации личности при подаче заявки на пользование любыми услугами.

Веб-приложение в данном сценарии предпочтительнее мобильного из-за своей доступности и сокращения времени на выполнение операции. Веб-страница не нуждается в инсталляции и готова к работе сразу после загрузки. Пользователь может перейти к выполнению необходимых ему действий – подаче заявки – сразу после получения ссылки, не отвлекаясь на дополнительные действия. С точки зрения бизнеса, эти факторы повышают конверсию и коммерческую эффективность процесса.

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

Требования


В рамках нашего проекта были следующие дополнительные требования к алгоритму:

  • возможность работы в режиме реального времени: видеопоток с камеры не должен “подтормаживать” в процессе работы алгоритма;
  • возможность работы в широком диапазоне контрастности и текстуры фона: малоконтрастный и контрастный, однородный и неоднородный фон;
  • поддержка широкого ряда моделей смартфонов, в том числе и бюджетных моделей, выпущенных несколько лет назад.

Наконец, датасет для тренировки алгоритмов машинного обучения в проекте отсутствовал, и не было возможности для его сбора и разметки. В нашем распоряжении было лишь несколько тестовых образцов из поисковой выдачи Google.

С учётом такой постановки задачи, мы приняли решение вести разработку на основе классических алгоритмов компьютерного зрения из библиотеки opencv. Альтернативной возможностью было использование алгоритмов машинного обучения и нейронных сетей, однако она была отброшена уже на ранних стадиях работы из-за требований к быстродействию: при их применении не удалось бы обеспечить обработку кадров в режиме реального времени на всех целевых устройствах.

Общий подход и структура алгоритма


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



Рис. 1. Общая структура алгоритма

Общая структура алгоритма изображена на рис. 1. Кадры из видеопотока обрабатываются в цикле, между итерациями которого выставляется таймаут для соблюдения желаемого FPS – мы остановились на 30 кадрах в секунду. Это позволяет избежать “подтормаживаний” и снизить нагрузку на процессор и энергопотребление устройства.

Каждый обрабатываемый кадр проходит препроцессинг, во время которого выполняются две основных операции. Во-первых, создаётся копия кадра фиксированного размера 640х480, с которой работают дальнейшие шаги алгоритма. Оригинальное изображение также остаётся, из него будет вырезан обнаруженный документ. Это позволит сохранить качество конечного изображения. Во-вторых, созданная копия переводится в оттенки серого. Цвет обрабатываемого документа игнорируется алгоритмом, так как он может меняться от страны к стране и даже в разных регионах внутри страны – примером служат водительские удостоверения в США.

Первым этапом детекции документа является поиск лица на изображении. Применение данной эвристики позволяет исключить захват визиток и прочих заведомо нерелевантных изображений. Поиск производится с помощью стандартного opencv’шного CascadeClassifier.detectMultiScale() и предобученного каскада haarcascade_frontalface_default. Минимальный и максимальный размеры обнаруживаемых лиц ограничиваются, что позволяет уменьшить вычислительные затраты, а также дополнительно ограничивает масштаб документа на изображении. Лицо считается обнаруженным на изображении, когда оно находится в левой – или левой нижней, для паспортов – части области внутри опорной рамки (рис. 2). Это дополнительная мера для обеспечения корректного выравнивания документа на изображении.

Приведенные в статье примеры не содержат персональных данных.



Рис. 2. Область ожидаемого положения лица на изображении. Красным цветом показана опорная рамка, зелёным – границы области ожидаемого расположения лица

После обнаружения лица переходим к обнаружению границ. Часто здесь применяется findContours(). Однако этот подход хорошо работает только в контрастных случаях, например, для листа бумаги, лежащего на письменном столе тёмного оттенка. Если контрастность ниже, или хуже освещение, или лист кто-то держит в руках, закрывая пальцами часть границы, обнаруживаемые контуры распадаются на отдельные компоненты, “теряют” значительные секции или вообще не обнаруживаются.

Поэтому мы применили другой подход. После бинаризации мы сначала пропускаем изображение через фильтр границ с помощью Canny(), а затем ищем на получившейся картине линии с помощью преобразования Хаффа HoughLines(). Параметр threshold сразу выставляем достаточно большим, равным 30 – для фильтрации обнаруживаемых коротких и других нерелевантных отрезков.

Получившийся набор линий дополнительно фильтруем, оставляя только линии, близкие к опорной рамке. Для этого предварительно переводим уравнения линий рамки в точки в полярной системе координат (rho, theta) – theta всегда будет равно 0 или pi/2, а rho будет уникальным для каждой линии. После этого отбираем из полученных из преобразования Хаффа линий только те, которые лежат в окрестности опорных точек – по евклидовой метрике с учётом разности масштабов значений.

Полученный после фильтрации набор линий распределяем по четырём группам, соответствующим четырём линиям опорной рамки, находим пересечения линий попарно между группами, усредняем и получаем координаты четырёх точек – углов обнаруженного документа (Рис.3).



Рис. 3. Фильтрация линий и определение углов документа. Зелёные линии – результат фильтрации, жёлтые точки – обнаруженные углы документа

Далее необходимо убедиться в качестве кадра. Для этого проверяем, что кадр оставался неподвижным в течение последнего времени. Для этого вычитаем из текущего кадра кадр на начало периода с помощью absdiff() и сравниваем с порогом. Перед вычитанием дополнительно сглаживаем изображения Гауссовым фильтром GaussianBlur() для уменьшения влияния шумов и других случайных факторов. Также мы проводим оценку сфокусированности кадра, вычисляя его лапласиан Laplacian(), оценивая его дисперсию и сравнивая полученное значение с порогом.

Если все проверки проходят успешно, можно переходить к финальной части. Пересчитываем обнаруженные координаты углов в систему координат исходного, неуменьшенного изображения и вырезаем полученный регион с помощью метода roi(). Документ обнаружен успешно.

Особенности реализации


В ходе разработки алгоритма основные его компоненты собирались в скрипте на python. После этого алгоритм был перенесён на opencv.js и javascript, а затем на wasm. Такой подход продиктован соображениями удобства работы на всех стадиях. На python нашей команде было удобнее экспериментировать с различными вариантами алгоритма и проводить грубую настройку параметров. Перенос на javascript позволил проверить работу алгоритма на целевой платформе, в том числе на различных устройствах и браузерах. По результатам этих проверок проводилась тонкая настройка параметров алгоритма. Наконец, переписывание критичных участков кода на wasm позволило получить дополнительный прирост быстродействия.

В ходе переноса обнаружился ряд различий в API OpenCV, повлекших незначительные изменения в реализации. Например, дисперсия лапласиана на python считается просто как Laplacian().var(). C OpenCV.js нет возможности пользоваться NumPy, но и альтернативной реализации метода var() не предоставлено. Решение: считать через функцию meanStdDev() – среднеквадратичное отклонение (листинг 1).

private isImageBlurry(image: cv.Mat): boolean {
		const laplacian = new cv.Mat();
		cv.Laplacian(image, laplacian, cv.CV_64F);
		const s_mat = new cv.Mat();
		cv.meanStdDev(laplacian, new cv.Mat(), s_mat);
		const s = s_mat.data64F[0];
		const v = Math.pow(s, 2);
		return (v < this.laplacianVarianceThreshold);
	}

Листинг 1. Оценка фокуса на изображении через дисперсию лапласиана в opencv.js (TypeScript)

Другой особенностью стала необходимость уменьшения размера библиотеки. В исходном виде OpenCV.js имеет объём 7,9 Мбайт. Её загрузка через интернет замедляет инициализацию алгоритма. Решение этой проблемы заключается в “обрезке” неиспользуемых модулей в процессе сборки библиотеки, что позволяет значительно уменьшить объём выходного файла: нам удалось добиться размера 1,8 Мбайт. Перечень включаемых в сборку компонентов может быть настроен в конфигурационном файле platforms/js/opencv_js.config.py (листинг 2).

white_list = makeWhiteList([core, imgproc, objdetect, video, dnn, features2d, photo, aruco, calib3d])

Листинг 2. Исходный white list модулей opencv, включаемых в сборку для javascript

Наконец, важный вклад в обеспечение требуемого быстродействия алгоритма был сделан за счет его выноса в Web Worker. Этот шаг вместе с ограничением FPS позволил избавиться от “подтормаживаний” видеопотока во время работы алгоритма, что положительно сказалось на UX.

Результаты


Примеры захвата и обрезки изображений показаны на рис. 4. Видно, что наиболее качественная обрезка достигается на темном однородном фоне, а наиболее низкое качество получается при светлом неоднородном фоне. Это ожидаемый эффект, связанный с получаемыми на разных фонах градиентами, используемыми при детекции границ документа. На тёмном фоне градиенты получаются большими, чем на светлом, однородный фон приводит к меньшей вариабельности значений градиента. Это приводит к надёжному обнаружению границ и, как следствие, к более качественной обрезке.




Рис. 4. Примеры обрезки документов с помощью алгоритма

Заключение


В статье представлен алгоритм обнаружения документов на кадрах из видеопотока, пригодный для использования в мобильных браузерах, а также рассмотрены особенности его реализации с помощью библиотеки opencv.js. Алгоритм позволяет получить на выходе изображения документов в качестве, достаточном для дальнейшего использования алгоритмами проверки подлинности, верификации личности и т.д. Быстродействие полученной реализации позволяет получить “гладкий” UX без “подтормаживаний” и потери кадров.

Спасибо за внимание! Надеемся, что статья была вам полезна.
Теги:
Хабы:
+7
Комментарии 0
Комментарии Комментировать

Публикации

Информация

Сайт
www.simbirsoft.com
Дата регистрации
Дата основания
Численность
1 001–5 000 человек
Местоположение
Россия