Как реализовать четырехточечное перспективное преобразование с использованием HTML5 canvas & three.js? - PullRequest
0 голосов
/ 01 января 2019

Во-первых, наглядный пример того, чего я пытаюсь достичь:

example

(Фото предоставлено: https://unsplash.com/photos/pGcqw1ARGyg)

Короткий (tl; dr) вопрос

Используя HTML5 video & canvas, как я могу выполнить четырехточечное перспективное преобразование, чтобы можно было визуализировать только часть "телевизионного экрана" кадра на холсте? Почемуне моя реализация показывает правильную область?

Справочная информация о том, чего я пытаюсь достичь

Я пытаюсь создать веб-страницу, которая работает следующим образом:

  1. Пользователь направляет свою веб-камеру на телевизор, чтобы он находился где-то в кадре (но, возможно, под любым углом)
  2. Используя HTML5-видео и холст, веб-камера захватывается иПредварительный просмотр на веб-странице
  3. Пользователь может определить (нажав на предварительный просмотр), где расположены 4 угла экрана телевизора (4 пары координат x / y)
  4. **Видео деформировано (с использованием какого-либо перспективного преобразования), поэтому на холсте только отображаютсячасть изображения для фактического экрана телевизора (не весь вид веб-камеры) **
  5. Затем выполняется некоторая обработка изображения (например, для определения наиболее заметных цветов).Эта часть выходит за рамки этого вопроса, кроме того, что я хочу иметь возможность получить доступ к содержимому / пикселям холста HTML5 в конце.

Часть, с которой я борюсь, этоШаг 4. Чтобы убедиться, что я обрабатываю только соответствующую часть изображения для каждого кадра видео, важно, чтобы я «деформировал» изображение так, чтобы оно показывало только область «экрана телевизора», а невся картинка с веб-камеры.

После небольшого прочтения, я понимаю, что:

  • Это требует некоторого вида преобразования перспективы, поскольку веб-камера может быть под любым углом, и мыне имеют дело с параллельными линиями, требуется 3-мерное преобразование, и 2D не будет достаточно.Это связано с тем, что 2D-преобразование (translate / rotate / scale / skew) не сможет работать со сходящимися сторонами.
  • HTML5-холст представляет собой двумерный контекст и поэтому может поддерживать только 2D-преобразования, а не 3Dпреобразования.Поскольку мне нужно решение, которое работает с canvas, я не могу просто использовать 3D CSS-преобразование (например, https://developer.mozilla.org/en-US/docs/Web/CSS/transform-function/matrix3d).. Это говорит о том, что, возможно, WebGL - это больше, чем мне нужно для работы с 3D-аспектом.

То, что я пытался сделать до сих пор

Имея это в виду, я попытался использовать следующий подход:

a) Захват веб-камеры с помощью тега video

b) Используя three.js , создайте трехмерную сцену, которая визуализируется в элементе canvas (чтобы я мог выполнить обработку изображения на полученном содержимом холста)

c) Сцена three.js состоит из: - плоской сетки, в которой показано видео с одной стороны, используя VideoTexture.- перспективная камера, изначально расположенная так, что она показывает все изображение веб-камеры

d) Разрешить пользователю нажимать на четыре угловые точки, чтобы определить, где находится его телевизор, выяснить, какие координаты х / у и сохранитьих

e) Рассчитайте перспективное преобразование, которое "растянет" изображение так, чтобы правильная область "заполнила кадр".Другими словами, растяните четыре щелкаемых «телевизионных угла» до четырех углов области просмотра.Я использовал эту библиотеку: https://github.com/jlouthan/perspective-transform для вычисления этого.

f) Я думаю, что если соответствующее преобразование применяется к мешу, содержащему видео, и камера остается в фиксированномположение, то выходной холст будет содержать требуемое изображение при просмотре в 2D.

Ссылка на мою текущую (неработающую) реализацию

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

https://bitbucket.org/mattwilson1024/perspective-transform/src/master/

Подводя итог

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

1 Ответ

0 голосов
/ 02 января 2019

Проблема с оригинальной реализацией заключается в том, как создавалось transformMatrix.

Мне удалось заставить его работать, изменив это:

transformMatrix.set(a1, a2, a3, 0, 
                    b1, b2, b3, 0, 
                    c1, c2, c3, 0, 
                    0,  0,  0,  1);

на следующее:

transformMatrix.set(a1, a2, 0, a3, 
                    b1, b2, 0, b3, 
                    0,  0,  0, 1, 
                    c1, c2, 0, c3);

Этот ответ на Math StackExchange был полезен для решения этой проблемы.

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

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