javascript - 如何使用HTML5 canvas和three.js实现4点透视变换?

标签 javascript typescript canvas three.js linear-algebra

首先,我要实现的视觉示例:

example

(照片来源:https://unsplash.com/photos/pGcqw1ARGyg

简短(tl; dr)问题

使用HTML5视频和画布,如何执行4点透视变换,以便仅渲染画布中帧的“电视屏幕”部分?为什么my implementation没有显示正确的区域?

我要达到的目标的背景

我正在尝试构建一个如下工作的网页:


用户将他们的网络摄像头指向电视,这样它就可以位于框架中的某个位置(但可能处于任何角度)
使用HTML5视频和画布,可在网页上捕获并预览网络摄像头
用户可以定义(通过单击预览)电视屏幕的四个角在哪里(4对x / y坐标)
**视频发生了扭曲(使用某种透视变换),因此画布仅显示其实际电视屏幕的图像部分(而不是整个网络摄像头视图)**
然后对图像执行一些处理(例如,识别最突出的颜色)。除了指出我将希望能够最后访问HTML5画布的内容/像素之外,这部分超出了此问题的范围。


我要努力处理的部分是第4步。为了确保我只处理视频每一帧的图像的相关部分,重要的是我“扭曲”图像,以便它仅显示“电视屏幕”区域,而不是整个网络摄像头图片。

经过一些阅读,我的理解是:


这需要某种透视变换,并且由于网络摄像头可以处于任何角度,并且我们不处理平行线,因此需要进行3维变换,而2D不够。这是因为2D变换(平移/旋转/缩放/偏斜)将无法处理会聚面。
HTML5 canvas是二维上下文,因此只能支持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元素的3D场景(以便我可以对生成的画布内容执行图像处理)

c)three.js场景包括:
  -包含一个扁平网格,其中使用VideoTexture在一侧显示视频。
  -透视摄像头,最初定位为可以显示整个摄像头图像

d)允许用户单击四个角点来定义他们的电视在哪里,确定x / y坐标是什么并保存它们

e)计算透视变换,该变换将“拉伸”出图像,以使正确的区域“充满帧”。换句话说,将四个单击的“电视角”点拉伸到视口的四个角。我一直在使用此库:https://github.com/jlouthan/perspective-transform进行计算。

f)我的想法是,如果将适当的变换应用于包含视频的网格,并且相机保持在固定位置,则当以2D观看时,输出画布将包含所需的图像。

链接到我当前(中断)的实现

这是我目前在上面所做的尝试的链接。它显示了视频,并允许您单击四个角。如果单击原点(在中心)周围的点,这似乎可行,但是问题是,如果您选择图像中其他位置的区域,则会显示错误的区域。

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

加起来

我非常感谢您提供任何帮助,弄清为什么它无法按我的预期进行工作,或者对是否有更好/更轻松的方法来实现我所需要的内容表示感谢。

最佳答案

原始实现的问题在于创建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);


This answer on the Math StackExchange对于解决此问题很有帮助。

为了将来任何人发现该问题的利益,我更新了原始问题,使其指向包含损坏代码的存档分支。可以在here中找到工作版本。

关于javascript - 如何使用HTML5 canvas和three.js实现4点透视变换?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53997984/

相关文章:

javascript - 2D Canvas(在 3D Canvas 后面)不绘制图像

javascript - 如何使 Canvas 上的文本移动动画更平滑(减少锯齿状运动)?

javascript - 扩大 UL 的过渡效应

javascript - 使用重力效果拖动元素

javascript - Typescript 中的导出和导入如何工作?

unit-testing - 单元测试 typescript 指令模板 karma-jasmine,未定义 html

javascript - 在 JavaScript 中检查当前玩家是否赢得了 Tic Tac Toe 游戏

javascript - 将不同的 JavaScript 对象合并到一个对象中

javascript - Angular 4 数组值丢失

html - 如何解决跨域安全错误。在 html 5 中使用 Canvas.getImageData