【问题标题】:Extract objects of specific colors and convert to paths提取特定颜色的对象并转换为路径
【发布时间】:2016-09-08 02:11:42
【问题描述】:

我有一个项目的想法,但我在开发它时遇到了困难。本质上,我想使用 JavaScript 分析图像(任何图像),采用特定颜色并将其作为路径映射到 HTML5 画布上。所有分析的图像将是不同颜色的基本形状。这是我想要它做的一个例子。

这个例子是我希望脚本在传递紫色十六进制引用时执行的操作。将蓝色传递给它会将画布输出更改为仅显示 2 个蓝色形状。有没有人知道如何在不使用插件的情况下实现这一点?画布输出将在某些时候被操纵,因此每个形状都需要有自己的独立路径(因为它们并不总是 4 边形状)。

【问题讨论】:

  • 任何图像 + 任何颜色 + 任何形状会使您的问题过于宽泛。但是还是有一些想法:画布中的“颜色”是 RGBA,如果目标有轻微的 RGBA 颜色变化,则很难匹配。您可以将所有 RGBA 值转换为 HSL,然后以色相为目标,从而为您提供更多颜色容差。 “形状”是不明确的,单个形状可能是多个不连贯部分的组合,但您可以使用Marching Squares 算法进行基本的边缘检测。

标签: javascript html canvas


【解决方案1】:

由于这个问题相当广泛,我不会提供代码,而是提供有关如何实现此目标的一般方法。

这些是需要采取的步骤:

第一遍:根据颜色和容差缩小图像。如果颜色是绝对的,只需迭代并创建像素与颜色不匹配的 Alpha 通道。对于公差,更好的方法是使用 RGB-HSL 转换,然后定义一个半径并检查读取的颜色是否在目标颜色的半径内。还要考虑 Alpha 通道值。

这将留下一个带有 alpha 通道的图像,并且只有你想要的颜色。

第二遍: 使用 Marching Squares 算法通过解决方案运行图像(无耻插件:受此问题的启发,我制作了自己的 here(MIT 许可证),它似乎比其他的更快,包括 D3 插件 - 但任何人都会这样做!)。通过迭代图像来提取路径,每次迭代都删除跟踪的部分。您可以通过使用组合模式destination-out 抚摸+填充获得的路径来完成此操作。根据您的场景使用大约 3-5 的线宽。

您可以使用 Ramer-Douglas-Peucker 来减少分数或保持原样。任何减分都不会带来准确的路径,但也会表现得更差。

第三遍:现在您有了路径数据,您可以使用这些数据从原始图像中剪裁出部分。添加所有路径数据(通过对每个路径使用 moveTo() 来使用子路径),然后使用合成模式删除不需要的像素。或者,如果您只追求路径:您就完成了!

【讨论】:

  • 您已经创建了一个不错的 Marching Squares 脚本。太棒了!
【解决方案2】:

要从画布中获取坐标(x, y) 像素的颜色分量,只需执行以下操作:

// assuming second canvas is same dimensions as first one
var secondCanvasId = context.createImageData(canvas.width, canvas.height);
for (var x = 0; x < canvas.width; x++) {
  for (var y = 0; y < canvas.height; y++) {
    var pix = context.getImageData(x, y, 1, 1).data;
    var r = pix[0];
    var g = pix[1];
    var b = pix[2];
    var a = pix[3];
    // set canvas2 (x, y) pixel with this color, if it matches the choosen color
    if (r === color.r && g === color.g && b === color.b && a === color.a) {
      secondCanvasId.data[0] = r;
      secondCanvasId.data[1] = g;
      secondCanvasId.data[2] = b;
      secondCanvasId.data[3] = a;
      context.putImageData(secondCanvasId, x, y);
    }
  }
}

【讨论】:

  • 这需要我知道块的 x,y 值是否正确?我需要它来自动检测颜色的 x,y 值。像这样的东西。 1. 脚本检查图像上的每个像素。 2.如果像素颜色等于指定颜色,则将其作为形状输出到画布上
  • 是的,只需将我的答案代码包含在一个双 for 循环中,以扫描画布中的所有像素(请参阅我更新的答案...)。
  • 谢谢,我现在就试一试,告诉你会发生什么:)
  • 抱歉,Marco 我对此有点迷茫。我对画布还很陌生。该脚本正在检查画布中的每个像素是否正确?它不应该扫描图像中的每个像素吗?那么如果像素数据匹配一个指定的值,输出到画布上呢?
  • new Color ?浏览器中没有 Color 对象。这是复制粘贴吗?一个源链接会很好。无论如何它不会解决OP的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-04-22
  • 2020-03-29
  • 2014-09-30
  • 2017-01-04
  • 2022-08-20
  • 2010-11-02
相关资源
最近更新 更多