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

Canvas实现盒模糊效果时如何仅对指定颜色区域应用模糊

仅对指定颜色生效的盒模糊实现方案

你现有代码已经具备目标色识别、原始像素备份、3x3盒模糊计算的核心逻辑,只需要在模糊计算前增加目标色判断,非目标色像素直接保留原始值即可。需要注意你原有全图模糊代码存在通道采样错误,会导致模糊后色偏,修正后的完整可运行代码如下:

var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("scream");
ctx.drawImage(img, 0, 0);    
var imgData = ctx.getImageData(0, 0, c.width, c.height);
var px = imgData.data;
// 存储完全未修改的原始像素副本,所有模糊采样都从该副本取值,避免逐像素修改时污染计算结果
var tmPx = new Uint8ClampedArray(px);
const imgWidth = imgData.width;
// 目标色值,完全复用你之前颜色反演逻辑的判断条件
const targetR = 243, targetG = 83, targetB = 37, targetA = 255;

// 按像素遍历,每个像素对应4个索引位(R/G/B/A)
for (let i = 0; i < px.length; i += 4) {
    // 判断当前像素是否为目标色
    const isTarget = tmPx[i] === targetR 
        && tmPx[i+1] === targetG 
        && tmPx[i+2] === targetB 
        && tmPx[i+3] === targetA;

    if (!isTarget) {
        // 非目标色直接保留原始值,不做模糊处理
        px[i] = tmPx[i];
        px[i+1] = tmPx[i+1];
        px[i+2] = tmPx[i+2];
        px[i+3] = tmPx[i+3];
        continue;
    }

    // 目标色像素执行3x3盒模糊计算,每个通道单独采样对应位置的原始值
    // R通道计算
    px[i] = (
        tmPx[i]
        + (tmPx[i - 4] ?? tmPx[i])
        + (tmPx[i + 4] ?? tmPx[i])
        + (tmPx[i - 4 * imgWidth] ?? tmPx[i])
        + (tmPx[i + 4 * imgWidth] ?? tmPx[i])
        + (tmPx[i - 4 * imgWidth - 4] ?? tmPx[i])
        + (tmPx[i + 4 * imgWidth + 4] ?? tmPx[i])
        + (tmPx[i - 4 * imgWidth + 4] ?? tmPx[i])
        + (tmPx[i + 4 * imgWidth - 4] ?? tmPx[i])
    ) / 9;

    // G通道计算
    px[i+1] = (
        tmPx[i+1]
        + (tmPx[i - 4 + 1] ?? tmPx[i+1])
        + (tmPx[i + 4 + 1] ?? tmPx[i+1])
        + (tmPx[i - 4 * imgWidth + 1] ?? tmPx[i+1])
        + (tmPx[i + 4 * imgWidth + 1] ?? tmPx[i+1])
        + (tmPx[i - 4 * imgWidth - 4 + 1] ?? tmPx[i+1])
        + (tmPx[i + 4 * imgWidth + 4 + 1] ?? tmPx[i+1])
        + (tmPx[i - 4 * imgWidth + 4 + 1] ?? tmPx[i+1])
        + (tmPx[i + 4 * imgWidth - 4 + 1] ?? tmPx[i+1])
    ) / 9;

    // B通道计算
    px[i+2] = (
        tmPx[i+2]
        + (tmPx[i - 4 + 2] ?? tmPx[i+2])
        + (tmPx[i + 4 + 2] ?? tmPx[i+2])
        + (tmPx[i - 4 * imgWidth + 2] ?? tmPx[i+2])
        + (tmPx[i + 4 * imgWidth + 2] ?? tmPx[i+2])
        + (tmPx[i - 4 * imgWidth - 4 + 2] ?? tmPx[i+2])
        + (tmPx[i + 4 * imgWidth + 4 + 2] ?? tmPx[i+2])
        + (tmPx[i - 4 * imgWidth + 4 + 2] ?? tmPx[i+2])
        + (tmPx[i + 4 * imgWidth - 4 + 2] ?? tmPx[i+2])
    ) / 9;

    // Alpha通道保持原始值
    px[i+3] = tmPx[i+3];
}

ctx.putImageData(imgData, 0, 0);
img.remove()

关键调整说明

  • 颜色判断逻辑完全复用你之前写反演效果时的规则,如果需要增加颜色容差(允许相近颜色也被模糊),直接修改isTarget的判断条件即可
  • 修正了原全图模糊代码的通道错位问题:原代码计算G、B通道模糊值时,邻域采样始终取R通道位置的数值,会导致模糊后颜色偏移,上述代码为R/G/B三个通道分别做了对应位置的邻域采样
  • 用空值合并运算符??替代原逻辑的||,避免邻域像素值为0时被错误判定为越界
  • 如果需要实现更自然的区域内模糊(模糊计算不混入周边非目标色的像素值),只需要在邻域采样时增加一层颜色判断:仅累加符合目标色的邻域像素值,最后用累加值除以实际参与计算的像素数量即可,不会出现目标色边缘晕入其他颜色的问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.26 19:18:46