Javascript 计算画布中两个“像素点”之间的最小距离

Javascript 计算画布中两个“像素点”之间的最小距离,javascript,algorithm,geometry,html5-canvas,euclidean-distance,Javascript,Algorithm,Geometry,Html5 Canvas,Euclidean Distance,我想计算两组像素之间的距离——为了便于说明,一组蓝色像素和一组红色像素。我想计算x方向、y方向和任意方向上的最近距离,请参见图像中的三个箭头。通常,一种颜色的像素可能是未连接的面片,如示例中的红色,但大多数情况下它们都是连接的,尽管在示例中它们可能有类似蓝色的孔 是否有任何库或算法已经以合理的方式解决了这一问题?想出一个解决方案并不特别困难——x和y距离是一个问题,但对于任意距离,朴素的暴力算法是可行的。我有一种预感,有更好的方法。如果你的集合没有像线段这样的特殊形状,你很难找到比On²更好的解

我想计算两组像素之间的距离——为了便于说明,一组蓝色像素和一组红色像素。我想计算x方向、y方向和任意方向上的最近距离,请参见图像中的三个箭头。通常,一种颜色的像素可能是未连接的面片,如示例中的红色,但大多数情况下它们都是连接的,尽管在示例中它们可能有类似蓝色的孔


是否有任何库或算法已经以合理的方式解决了这一问题?想出一个解决方案并不特别困难——x和y距离是一个问题,但对于任意距离,朴素的暴力算法是可行的。我有一种预感,有更好的方法。

如果你的集合没有像线段这样的特殊形状,你很难找到比On²更好的解决方案

但您可以添加预处理步骤以减少n。移除集合的所有内部点。这取决于集合,可能会显著降低n。在您的示例中,我估计这将使n的大小减少一半


如果您的示例是集合的典型示例,则可以将集合转换为一组线段,然后计算它们之间的距离。

如果集合没有像线段那样的特殊形状,则很难找到比On²更好的解决方案

但您可以添加预处理步骤以减少n。移除集合的所有内部点。这取决于集合,可能会显著降低n。在您的示例中,我估计这将使n的大小减少一半


如果您的示例是集合的典型示例,您可以将集合转换为一组线段,然后计算它们之间的距离。

您可以计算任意形状的水滴周围的全距离贴图,包括线性时间上的断开,无论是曼哈顿还是欧几里德,其中n表示图像大小

当你有了这个地图,扫描其他的斑点来找到最小值也只需要打开


请看这篇精彩的文章:

您可以计算任意形状的水滴周围的全距离贴图,包括线性时间上的断开,无论是曼哈顿还是欧几里德,其中n表示图像大小

当你有了这个地图,扫描其他的斑点来找到最小值也只需要打开

请参阅这篇精彩的文章:

使用GPU 使用canvas 2D API,您对GPU的访问受到限制,您可以利用GPU发挥优势

如果这两种颜色是单独的通道,因为您有红色和蓝色,并且没有其他颜色会把事情搞砸,那么您可以使用GPU缩小图像的比例,以减少初始搜索

创建工作画布

const can = document.createElement("canvas");
var w = can.width = ctx.canvas.width;
var h = can.height = ctx.canvas.height;
const ctxW = can.getContext("2d");
设置平滑和混合模式复制

将原始画布缩小一半

// first step move original to working canvas
w /= 2;
h /= 2;
ctxW.drawImage(ctx.canvas, 0, 0, w, h);

// Reduce again drawing onto its self
ctxW.drawImage(ctxW.canvas, 0, 0, w, h, 0, 0, w / 2, h / 2);
w /= 2;
h /= 2;
ctxW.drawImage(ctxW.canvas, 0, 0, w, h, 0, 0, w / 2, h / 2);

const imgData = ctxW.getImageData(0, 0, w / 2, h / 2); // 1/64th as many pixels 
在这一点上,缩小的画布的大小是1/8,更好的是,它有82个像素要处理

缩放由GPU完成

然后,您可以通过蛮力方法搜索这些像素,创建候选像素列表。请注意,如果红色和蓝色的距离小于8像素,则在某些情况下,它们将占据相同的像素

然后返回到原始画布,优化缩小像素数据中找到的候选对象的接近度

这并不是对On2的真正改进,而是在利用GPU提供的并行处理能力时获得的巨大性能提升

还请注意,当您减少每个步骤时,您在工作画布上有足够的空间来保留每个减少,这意味着您可以在细化候选区域时通过减少进行备份,从而节省更多时间。

使用GPU 使用canvas 2D API,您对GPU的访问受到限制,您可以利用GPU发挥优势

如果这两种颜色是单独的通道,因为您有红色和蓝色,并且没有其他颜色会把事情搞砸,那么您可以使用GPU缩小图像的比例,以减少初始搜索

创建工作画布

const can = document.createElement("canvas");
var w = can.width = ctx.canvas.width;
var h = can.height = ctx.canvas.height;
const ctxW = can.getContext("2d");
设置平滑和混合模式复制

将原始画布缩小一半

// first step move original to working canvas
w /= 2;
h /= 2;
ctxW.drawImage(ctx.canvas, 0, 0, w, h);

// Reduce again drawing onto its self
ctxW.drawImage(ctxW.canvas, 0, 0, w, h, 0, 0, w / 2, h / 2);
w /= 2;
h /= 2;
ctxW.drawImage(ctxW.canvas, 0, 0, w, h, 0, 0, w / 2, h / 2);

const imgData = ctxW.getImageData(0, 0, w / 2, h / 2); // 1/64th as many pixels 
在这一点上,缩小的画布的大小是1/8,更好的是,它有82个像素要处理

缩放由GPU完成

然后,您可以通过蛮力方法搜索这些像素,创建候选像素列表。请注意,如果红色和蓝色的距离小于8像素,则在某些情况下,它们将占据相同的像素

然后返回到原始画布,优化缩小像素数据中找到的候选对象的接近度

这并不是对On2的真正改进,而是在利用GPU提供的并行处理能力时获得的巨大性能提升

还请注意,当您减少每个步骤时,您在工作画布上有足够的空间来保持每个减少,这意味着您可以在细化候选区域时通过减少进行备份,甚至可以节省m
更多时间。

是的,去除像素绝对是一件好事。但可能存在登录n解决方案。我发现这一点很重要。不过,我必须检查它是否真的涵盖了我的问题。是的,去除像素绝对是一件好事。但可能存在登录n解决方案。我发现这一点很重要。不过,我得检查一下它是否真的涵盖了我的问题。我不知道为什么会有人对此投反对票。这是一个伟大而优雅的解决方案,甚至可以通过npm安装距离转换实现。依赖性有点过火了——我期待着有机会真正理解为什么数学是有效的,并将我自己的版本作为一个有趣的项目来实现。这种数学解决方案真的很吸引我。非常感谢@这是一种扫描线程序。计算沿单行的最短距离,并在从一行移动到下一行时保持该距离。曼哈顿距离的理论很简单。对于欧几里得,这是更少的。请注意,删除内部点会适得其反。我不知道为什么会有人对此投反对票。这是一个伟大而优雅的解决方案,甚至可以通过npm安装距离转换实现。依赖性有点过火了——我期待着有机会真正理解为什么数学是有效的,并将我自己的版本作为一个有趣的项目来实现。这种数学解决方案真的很吸引我。非常感谢@这是一种扫描线程序。计算沿单行的最短距离,并在从一行移动到下一行时保持该距离。曼哈顿距离的理论很简单。对于欧几里得,这是更少的。请注意,删除内部点会适得其反。