有没有更有效的坐标变换方法?

Posted

技术标签:

【中文标题】有没有更有效的坐标变换方法?【英文标题】:Is there a more effective way to transform coordinates? 【发布时间】:2022-01-19 13:00:21 【问题描述】:

我在画布上有一张图片,我想对其进行梯形失真。代码本身已经准备好了,但是很慢,很慢。在 i7 台式机上,约 10-20 秒内可显示 400x400 图像。但是,我想在具有最大相机分辨率的移动设备上运行它,所以我正在寻找一种更有效的方法。 目前,我的代码是这样工作的:

    向用户请求扭曲矩形的坐标。我需要从用户那里得到正交坐标 我将边 a 和 c 分成 400 个部分。 我迭代了之前的划分,所以我取“a”边 1/400 部分的点和“c”边 1/400 部分的点。然后是 2/400 部分上的点之间的部分。等等。 我将刚刚生成的部分除以 400 并对其进行迭代。 我将点 2 中产生的行号作为“X”,将点 4 中的点作为“Y”。给定点的坐标是 Q 和 W。 我将原始画布上坐标“Q”和“W”处的像素绘制到目标画布上由坐标“X”和“Y”标识的位置。

有没有更有效的方法来做到这一点?

【问题讨论】:

起草了一个非仿射变换提案here,它甚至在 Chrome 中实现了一段时间,但不幸的是,所有图形引擎本身都不支持这种变换,它已被“停放”暂时。 【参考方案1】:

由于您本质上是在像素级别上操作,所以事情必须非常缓慢。最快的方法是利用 WebGL 并将计算外包给片段着色器。不过,在这种情况下,这可能有点矫枉过正。如果您只想从透视角度转换图像,那么有一个现成的小型库 - 虽然不如像素级别那么精确 - 可能会满足您的需求,称为 perspective.js

你所要做的就是给它一个图像和你想要的四个角点。

这是一个例子:

let canvas = document.getElementById("canvas");
let image = new Image();
image.onload = function() 
  let ctx = canvas.getContext("2d");
  let p = new Perspective(ctx, image);

  p.draw([
    [65,43],
    [266, 16],
    [304,251],
    [26,151]
  ]);

image.src = "https://picsum.photos/id/1079/200/300";
canvas 
  border: gray solid 1px;
<script src="https://cdn.rawgit.com/wanadev/perspective.js/master/dist/perspective.min.js"></script>
<canvas id="canvas"  ></canvas>

【讨论】:

感谢您的回答。这个小小的库很棒,而且足够快。但我需要逆变换。所以我有原始图像,我想从中突出显示一部分。不要把整个图像放在透视图中。我看到这两个操作非常相似,但我不知道如何应用这个解决方案。你能帮我解决这个问题吗? 冲动地我会说这是可行的,但我不确定突出显示会是什么样子。也许您可以在原始问题中添加图片? 好吧,我不是一个好的抽屉,我第一次尝试画这个,但我想我失败了。我会试着把它写下来 :) 所以我想将原始图纸上边为“abcd”的四边形拉伸到与包含它的图片相同的大小。因此,如果我在 100x100 图像上有“abcd”四边形,那么在转换后“d”边的端点是 (0;0) 和 (0;100)。同样,“b”边的端点将是 (100;0) 和 (100;100),无论图形中的四边形具有什么坐标。这是我需要的转变。 我的脑海里恐怕还是没有画面。 =) 使用你的工作非常慢的算法来处理输入图像并发布它的输入和输出怎么样?

以上是关于有没有更有效的坐标变换方法?的主要内容,如果未能解决你的问题,请参考以下文章

OpenGL里的坐标系统以及其变换

数字图像处理仿射变换与透视变换

三维图形变换

怎么用arcgis进行WGS84的投影坐标变换

arcgis坐标转换

坐标变换的七个参数