You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用JavaScript为图片的不同白色区域独立着色?

给图片中独立白色区域分色的实现方案

核心思路

你之前的问题在于未区分连通的白色区域,只是全局替换白色像素。要实现分区域着色,必须用连通区域检测+区域填充的思路——比如用广度优先搜索(BFS):遍历每个像素,找到未处理的白色像素作为起点,然后把所有和它连通的白色像素(四/八方向相邻)标记为同一颜色,同时记录已处理像素避免重复操作。

具体实现代码

<canvas id="canvas"></canvas>
<script>
// 加载目标图片
const img = new Image();
img.crossOrigin = "anonymous"; // 处理跨域,按需调整
img.src = "你的图片路径"; // 替换为实际图片地址

img.onload = function() {
  const canvas = document.getElementById('canvas');
  const ctx = canvas.getContext('2d');
  canvas.width = img.width;
  canvas.height = img.height;
  ctx.drawImage(img, 0, 0);

  // 获取像素数据
  const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
  const data = imageData.data;
  const width = imageData.width;
  const height = imageData.height;
  // 标记已处理的像素,防止重复遍历
  const visited = new Uint8Array(width * height);

  // 生成随机区分色
  function getRandomColor() {
    const r = Math.floor(Math.random() * 255);
    const g = Math.floor(Math.random() * 255);
    const b = Math.floor(Math.random() * 255);
    return [r, g, b];
  }

  // 四连通方向:上下左右(需要八连通的话,添加对角线方向即可)
  const directions = [[-1,0], [1,0], [0,-1], [0,1]];

  // 遍历所有像素,寻找未处理的白色区域
  for (let y = 0; y < height; y++) {
    for (let x = 0; x < width; x++) {
      const index = y * width + x;
      const pixelIndex = index * 4;
      // 检测未访问的纯白像素(可根据实际白色灰度调整判断条件)
      if (data[pixelIndex] === 255 && data[pixelIndex+1] === 255 && data[pixelIndex+2] === 255 && !visited[index]) {
        const [r, g, b] = getRandomColor();
        // BFS队列存储区域内的像素坐标
        const queue = [[x, y]];
        visited[index] = 1;

        // 遍历当前连通区域的所有像素
        while (queue.length > 0) {
          const [currX, currY] = queue.shift();
          const currPixelIndex = (currY * width + currX) * 4;
          // 为当前像素着色
          data[currPixelIndex] = r;
          data[currPixelIndex+1] = g;
          data[currPixelIndex+2] = b;

          // 检查相邻像素是否属于同一区域
          for (const [dx, dy] of directions) {
            const newX = currX + dx;
            const newY = currY + dy;
            // 确保坐标在画布范围内
            if (newX >= 0 && newX < width && newY >=0 && newY < height) {
              const newIndex = newY * width + newX;
              const newPixelIndex = newIndex *4;
              // 若为未访问的白色像素,加入队列并标记
              if (data[newPixelIndex] ===255 && data[newPixelIndex+1] ===255 && data[newPixelIndex+2] ===255 && !visited[newIndex]) {
                visited[newIndex] =1;
                queue.push([newX, newY]);
              }
            }
          }
        }
      }
    }
  }

  // 将处理后的像素数据绘制回画布
  ctx.putImageData(imageData, 0, 0);
};
</script>

关键细节说明

  • 连通规则:代码用四连通(上下左右),如果需要包含对角线的八连通,在directions数组中添加[-1,-1], [-1,1], [1,-1], [1,1]即可。
  • 颜色适配:假设目标图片白色为纯RGB(255,255,255),如果是灰度白色,可调整判断条件(比如data[pixelIndex] > 240)。
  • 效率优化:visited数组避免重复处理同一像素,大幅提升遍历效率。
  • 颜色自定义:可以把随机颜色换成固定颜色列表,按顺序取用,实现更可控的分色效果。

原思路问题分析

你之前的逻辑仅检测白色像素着色、遇黑色停止,本质是全局替换所有白色,没有识别“连通区域”——只有用BFS/DFS这类算法,才能把连在一起的白色像素视为一个独立区域,实现分色目标。

内容的提问来源于stack exchange,提问作者Nour Hariz

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 04:55:45