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

Эта статья о том, как объединить несколько изображений в одно длинное.

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

Как вообще прошивка работает? Мы берем два изображения с перекрывающимися областями, вычисляем взаимное смещение друг от друга и смешиваем их. Звучит довольно просто, но давайте рассмотрим каждый шаг.

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

Как мы видим, на этих фотографиях много общих объектов:

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

Одним из таких алгоритмов является SIFT (масштабно-инвариантное преобразование признаков). Несмотря на то, что он был изобретен в 1999 году, он до сих пор пользуется большой популярностью благодаря своей простоте и надежности. Поскольку SIFT запатентован, он является частью несвободной сборки OpenCV, но срок действия патента недавно истек (в марте 2020 года), поэтому он, вероятно, скоро станет частью стандартного OpenCV.

Теперь давайте найдем схожие черты на обоих изображениях:

Использование сопоставителя на основе Флана позволяет относительно быстро находить совпадения между двумя изображениями, несмотря на большое количество углов.

Желтые линии на картинке ниже соединяют схожие черты на левом и правом изображениях.

Для наглядности изображения были размещены друг над другом с правильным смещением (которое рассчитывается на более позднем этапе процесса, а не здесь).

Как нетрудно заметить, несоответствий по-прежнему много - около 50% из них ошибочны. Однако хорошие совпадения всегда будут давать один и тот же перевод, в то время как плохие будут давать хаотично разные направления. На картинке ниже показаны только хорошие совпадения:

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

К счастью, OpenCV предоставляет несколько вариантов поиска гомографии с помощью RANSAC - разница между методами заключается в размерах свободы, которую будет иметь преобразование. В нашем случае нам нужно использовать EstimationAffinePartial2D, который будет искать следующие преобразования: вращение + масштабирование + перемещение (4 измерения свободы).

Левое изображение:

Правильное изображение:

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

Анимация показывает сдвиг между плитками:

Это не удивительно - изображения были сняты под немного разными углами, и между ними есть небольшие различия.

Для бесшовной вышивки необходимо компенсировать эти нелинейные искажения. Искажение можно описать как гладкое векторное поле с тем же разрешением, что и исходные плитки. Это векторное поле называется «оптическим потоком».

Существует несколько методов расчета потока - с помощью функций, которые поставляются с OpenCV или специальной архитектурой нейронных сетей.

Наш оптический поток для данных двух плиток:

Чтобы избежать артефактов при сшивании, необходимо пропорционально компенсировать оба изображения. Для этого разделим оптический поток на две матрицы:

Теперь два изображения почти идеально выровнены:

Когда мы смешиваем полное изображение, оно кажется геометрически правильным, но мы наблюдаем скачок яркости:

Проблему довольно легко исправить, если вместо средних значений использовать формулу смешивания, в которой значения применяются с градиентом:

При таком подходе сшивание будет абсолютно бесшовным:

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

Сшиваем весь набор изображений:

Конечный результат:

Дальнейшие улучшения могут включать компенсацию эффекта тени (правая часть изображения) и даже дополнительную постобработку для улучшения цветов и контрастности.

Здесь мы узнали, как работает сшивание и как сделать его бесшовным для производственного использования.

Рекомендуемые ссылки:

  1. SIFT объяснил: https://docs.opencv.org/master/da/df5/tutorial_py_sift_intro.html
  2. Объяснение омографии OpenCV https://docs.opencv.org/master/d9/dab/tutorial_homography.html
  3. Автошивка панорамы http://matthewalunbrown.com/papers/ijcv2007.pdf
  4. OpenPano https://github.com/ppwwyyxx/OpenPano
  5. Сканер фотографий Google https://ai.googleblog.com/2017/04/photoscan-taking-glare-free-pictures-of.html