Perspective Transformation

Perspective Transformation

Если вбить в поисковике фразу «Перспективная трансформация» половина выдачи будет посвящено психологии. Народ интересуется личностным преображением на карантине и кормит доморощенных психологов.

Поэтому Perspective Transformation. К личностной деформации не имеет никакого отношения.

Что под эти этом понимается? Это не аффинное преобразование, это произвольная деформация прямоугольника картинки по четырем точкам с адекватным искажением содержимого.

Рис.1. Перспективное преобразование

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

Graphics32

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

Предполагаю, что все пути прописаны в Options — Library правильно. Для реализации перспективной трансформации методом Graphics32 понадобятся следующие модули: GR32, GR32_Transforms, GR32_Resamplers.

Перспективная трансформация Graphics32

[свернуть]

Параметры:

В демонстрационном проекте представлен урезанный вариант библиотеки. Распространением библиотек этот сайт не занимается. Тут всегда представлен только необходимый для работы приложения минимум. Скачать и поставить полный комплект (исходники, компоненты, примеры) можно по этой ссылке.

Рис.2. Graphics32

OpenCV

Легендарная библиотека компьютерного зрения, обработки изображений и массы всего другого. Тащит с собой внушительный набор dll. Написана на С/С++, поэтому дополнительно включает в себя ряд обязательных библиотек от VC.

Есть библиотека для Delphi. Но для устаревшей (но не потерявшей от этого своей прелести и функциональности) версии 2.4.13. При установке следуем инструкции в той части, которая касается непосредственно Delphi.

Недостающие dll для OpenCV 2.4.13 берем тут.

Библиотеки VC можно взять из демонстрационного проекта. В проекте использованы только «нужные» библиотеки OpenCV, тащить весь набор смысла нет. Зато присутствует набор для VC. Как минимум:

  • MSVCP140D.dll
  • VCRUNTIME140D.dll
  • consrt140d.dll
  • ucrtbased.dll

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

Снова отдельный модуль OCVProjectiveTransform и функция OCVPerspTransformBitmap с абсолютно таким же набором параметров, как и в GR32PerspTransformBitmap. Есть дополнительно еще две функции, одна для перевода стандартного для Delphi TBitmap в формат представления, понятного OpenCV PIplImage:

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

function cvImage2Bitmap(img: PIplImage): TBitmap;

Как не трудно догадаться, осуществляет обратное преобразование.

Для перспективных (и не только) трансформаций необходимым и достаточным является набор из следующих модулей:

  • ocv.highgui_c
  • ocv.core_c
  • ocv.core.types_c
  • ocv.imgproc_c
  • ocv.imgproc.types_c
Перспективная трансформация OpenCV

[свернуть]

При написании функции OCVPerspTransformBitmap за основу был взят пример cv_WarpPerspective (samples\LibDemo\cvWrapPrespective). Безусловно, намного более очевидный, чем в Graphics32.

ВНИМАНИЕ! В демо примере используются библиотеки только для режима DEBUG (буковка d в конце названия библиотек) . Чтобы заработало в RELEASE — удалите эту буковку или продублируйте библиотеки и удалите «d». Однако, самый лучший способ, это взять полный набор библиотек, ссылка на которые представлена выше.

DEBUGRELEASE
opencv_core2413d.dllopencv_core2413.dll
opencv_highgui2413d.dllopencv_highgui2413.dll
opencv_imgproc2413d.dllopencv_imgproc2413.dll

Сравнение Graphics32 и OpenCV

Рис.3. OpenCV

Сравним рис.2. и рис.3. Два трансформированных изображения. Координаты и исходные изображения одни и те же. Разные методы получения. Сравним время:

МетодНебоГород
Graphics320.02810.0189
OpenCV0.11510.0317
Таб.1. Сравнение времени работы методов

OpenCV явно проигрывает. С чем это связано. Если заглянуть в исходники, то можно убедиться, что OpenCV «честно» решает систему линейных уравнений. По сути, решает проблему «в лоб».

Если были скачаны исходники библиотек OpenСV 2.4.13, то в модуле opencv\sources\modules\imgproc\src\imgwarp.cpp находим такой код:

Составление матрицы уравнений перспективной трансформации в OpenCV

[свернуть]

Что имеем: с одной стороны очень быстрый Graphics32, которые требует распространяться под такой же лицензией и открытым кодом, с другой — более медленный OpenCV, который всего этого не требует, но тащит за собой внушительный прицеп из dll.

Однако, если использовать модули из указанной выше библиотеки OpenCV для Delphi, то помимо прицепа c dll, действуют те же правила, что и для Graphics32 — и код открытый, и лицензия такая же.

Конечно пишем свой вариант. Зачем? Есть ряд вещей (о которых частично ниже), которые меня не устраивают в реализации. Второе, не устраивает лицензия.

IP76

Составление матрицы системы уравнений, ее решение, нахождение коэффициентов — путь явно более медленный, чем тот, который предлагает Graphics32 (см.таб.1).

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

Рис.4. IP76 vs Graphics32

На рисунке плохо видно, но IP76: 10.6 миллисекунд, GR32: 11.8 миллисекунд. Чем больше картинка, тем выигрыш ощутимей.

Рис.5. IP76 vs Graphics32 (7.9 msec / 11.4 msec)
Матрица перспективной трансформаций IP76

[свернуть]

Билинейный фильтр в моей реализации сделан исключительно по теории, без целочисленной оптимизации, что чуть влияет на скорость.

Билинейный фильтр

[свернуть]

Функция перспективной трансформации:

Создание изображения в перспективной трансформации IP76

[свернуть]

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

Рис.6. IP76

Расширим таблицу 1 с учетом своей реализации:

МетодНебоГород
Graphics320.02810.0189
OpenCV0.1151
(4,1 * GR32)
0.0317
(1.68 * GR32)
IP760.0364
(1.3 * GR32)
0.0273
(1.44 * GR32)
Таб.2. Сравнение времени работы всех методов

Своя реализация с применением билинейной фильтра примерно в 1.4 медленнее чем Graphics32 и сильно быстрее, чем OpenCV.

Глюки реализаций

Алгоритм и Graphics32, и OpenCV, построен таким образом, что если фигура, отображаемая на экране имеет размеры большие, чем исходное изображение, вывод на экран «обрезается».

Рис.7. Graphics32 (22.8 msec)
Рис.8. OpenCV (270.5 msec)

Проблему можно решить увеличив исходное изображение. Но это как-то искусственно и «костыльно». Либо поправив руками исходники, что тоже не самый лучший путь.

Конечно, эта проблема решена в IP76.

Рис.9. IP76 (34.7 msec)

«Шедевры»

Рис.10. Река-небо, небо-отражение заката в реке
Рис.11. Потерянный

Коллеги, спасибо за внимание!

Информация о новых статьях всегда и только в телеграм-канале. Никаких рассылок на почту.

Не забываем комментировать, ругаться и подписываться )))


Скачать (4.3 Мб): Исходники (Delphi XE 7-10)

Скачать (7.8 Мб): Исполняемый файл


5 12 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Межтекстовые Отзывы
Посмотреть все комментарии
0
Не нашли ответ на свой вопрос? Задайте его здесь!...x