用 javascript 标记像素的连通分量?

Connected components labeling pixels with javascript?

我有一组像素。从一开始我就需要从 PNG 中删除黑色背景,然后以某种方式将剩余的白色像素分组到数组中。每个子数组都对应于像素(形状)斑点坐标。问题是如何在 javascript 中进行连接组件标记?也许有一个图书馆可以做到这一点?

[[10,34,34,10],[72, 300, 72, 30]]

这是我去除黑色像素的方法:

   const black2transparent = (img: HTMLImageElement) => {
    const c = document.createElement("canvas");

    const w = img.width;
    const h = img.height;

    c.width = w;
    c.height = h;

    const ctx = c.getContext("2d");

    if (!ctx) {
      return "";
    }

    ctx.drawImage(img, 0, 0, w, h);
    const imageData = ctx.getImageData(0, 0, w, h);

    const pixel = imageData.data;

    const r = 0;
    const g = 1;
    const b = 2;
    const a = 3;

    for (let p = 0; p < pixel.length; p += 4) {
      if (pixel[p + r] === 0 && pixel[p + g] === 0 && pixel[p + b] === 0) {
        pixel[p + a] = 0;
      }
    }


    ctx.putImageData(imageData, 0, 0);

    return c.toDataURL("image/png");
  };
const black2transparent = (img: HTMLImageElement) => {
    const c = document.createElement("canvas");

    const w = img.width;
    const h = img.height;

    c.width = w;
    c.height = h;

    const ctx = c.getContext("2d");

    if (!ctx) {
      return "";
    }

    ctx.drawImage(img, 0, 0, w, h);
    const imageData = ctx.getImageData(0, 0, w, h);

    const pixel = imageData.data;

    const r = 0;
    const g = 1;
    const b = 2;
    const a = 3;

    let x = 1;
    let y = 0;
    const whiteLines = [];
    let lastWhitePixelStart = null;

    for (let p = 0; p < pixel.length; p += 4) {
      if (p > 0 && p % (w * 4) === 0) {
        x = 1;
        lastWhitePixelStart = null;
        y += 1;
      } else {
        x += 1;
      }

      if (pixel[p + r] === 0 && pixel[p + g] === 0 && pixel[p + b] === 0) {
        pixel[p + a] = 0;

        if (lastWhitePixelStart !== null) {
          whiteLines.push([lastWhitePixelStart, { x, y }]);
          lastWhitePixelStart = null;
        }
      } else {
        if (lastWhitePixelStart === null) {
          lastWhitePixelStart = { x, y };
        }
      }
    }

    const blobs: MaskDataType[] = [];
    while (whiteLines.length) {
      let line = whiteLines.shift();
      if (!line) break;
      let categorized = false;

      for (let i = 0; i < blobs.length; i += 1) {
        let blob = blobs[i];

        if (blob.maxY + 2 < line[0].y) continue;

        if (blob.minX > line[1].x || blob.maxX < line[0].x) {
          continue;
        }

        blob.maxY = line[0].y;
        blob.minX = Math.min(blob.minX, line[0].x);
        blob.maxX = Math.min(blob.maxX, line[1].x);
        blob.lines.push(line);
        categorized = true;
      }

      if (!categorized) {
        blobs.push({
          minY: line[0].y,
          maxY: line[0].y,
          minX: line[0].x,
          maxX: line[1].x,
          lines: [line],
        });
      }
    }

    // blob contains array of white pixels coordinates
    setMaskData(blobs);

    ctx.putImageData(imageData, 0, 0);

    return c.toDataURL("image/png");
  };

像素数组在 blob 中