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

请求解析图像卷积矩阵算法原理及模糊效果示例代码

Understanding Image Blur via Convolution Matrix: Code Breakdown

Alright, let's unpack this convolution code line by line to see exactly how it creates that soft blur effect. First, a quick recap of the core idea: Convolution works by sliding a small matrix (your weights array here) over every pixel in the image. For each output pixel, we calculate a weighted sum of the surrounding source pixels that sit under the matrix. For blur, these weights are usually equal (or normalized) so we're just averaging nearby pixels.

Now let's walk through the code step by step:

1. Setup: Temporary Canvas Helper

Filters.tmpCanvas = document.createElement('canvas');
Filters.tmpCtx = Filters.tmpCanvas.getContext('2d');
Filters.createImageData = function(w,h) { return this.tmpCtx.createImageData(w,h); };
  • We create an off-screen canvas and its context here—this is just a quick helper to generate empty ImageData objects later. Browsers require a canvas context to use createImageData, so this wrapper makes it easier to spin up blank image data of a specific width/height.

2. The Main Convolution Function: Filters.convolute

This is where all the action happens. Let's start with its parameters:

  • pixels: The source image data (from canvas.getContext('2d').getImageData()). It has a data array with raw RGBA values (each pixel uses 4 entries: red, green, blue, alpha) plus width and height properties.
  • weights: The convolution matrix, flattened into a single array. For example, a 3x3 blur matrix would be [1,1,1,1,1,1,1,1,1] (you'd usually normalize this to 1/9 per entry to keep brightness consistent).
  • opaque: A boolean flag to force the output image to be fully opaque, if needed.

Step 2.1: Figure Out the Matrix Size

var side = Math.round(Math.sqrt(weights.length));
var halfSide = Math.floor(side/2);
  • Since weights is a flattened array (like 9 elements for a 3x3 matrix), we find the matrix's side length by taking the square root of the array length.
  • halfSide tells us how far the matrix extends from the center pixel. For a 3x3 matrix, this is 1—meaning we look 1 pixel up, down, left, and right from the current pixel.

Step 2.2: Prep Source & Destination Data

var src = pixels.data;
var sw = pixels.width;
var sh = pixels.height;
var w = sw;
var h = sh;
var output = Filters.createImageData(w, h);
var dst = output.data;
  • src is a direct reference to the source image's raw RGBA data array.
  • sw and sh store the source image's width and height.
  • We create an output ImageData object (same size as the source) to hold our blurred result, and dst points to its raw data array where we'll write the final pixel values.

Step 2.3: Opaque Handling Setup

var alphaFac = opaque ? 1 : 0;
  • If opaque is true, we'll force every pixel's alpha channel to 255 (fully opaque) later. This alphaFac multiplier makes that calculation straightforward.

Step 2.4: Loop Through Every Output Pixel

for (var y=0; y<h; y++) {
    for (var x=0; x<w; x++) {
        var sy = y;
        var sx = x;
        var dstOff = (y*w+x)*4;
        // ... weighted sum calculation ...
        // ... write values to destination ...
    }
}
  • We loop over every x/y coordinate in the output image—this means we process one pixel at a time.
  • dstOff calculates the index in the dst array for the current pixel: each pixel takes 4 entries (RGBA), so we multiply the pixel's linear position (y*w + x) by 4 to get the starting index.

Step 2.5: Calculate the Weighted Sum for the Current Pixel

var r=0, g=0, b=0, a=0;
for (var cy=0; cy<side; cy++) {
    for (var cx=0; cx<side; cx++) {
        var scy = sy + cy - halfSide;
        var scx = sx + cx - halfSide;
        if (scy >= 0 && scy < sh && scx >= 0 && scx < sw) {
            var srcOff = (scy*sw+scx)*4;
            var wt = weights[cy*side+cx];
            r += src[srcOff] * wt;
            g += src[srcOff+1] * wt;
            b += src[srcOff+2] * wt;
            a += src[srcOff+3] * wt;
        }
    }
}
  • We initialize r, g, b, a to 0—these will hold the running total of weighted values for each color channel.
  • The inner loops iterate over every cell in the convolution matrix (cy = matrix row, cx = matrix column).
  • scy and scx calculate which source pixel corresponds to the current matrix cell: we offset from the destination pixel (sy/sx) by cy - halfSide and cx - halfSide—this centers the matrix perfectly on the destination pixel.
  • The if check ensures we don't try to access pixels outside the source image (like negative coordinates or ones beyond the image's width/height—no out-of-bounds errors here!).
  • srcOff is the index in the source data array for the current source pixel we're looking at.
  • wt is the weight from the convolution matrix for this cell. We multiply each source channel value by this weight and add it to our running totals. For blur, this is like averaging all the pixels in the matrix.

Step 2.6: Write the Calculated Values to the Output Pixel

dst[dstOff] = r;
dst[dstOff+1] = g;
dst[dstOff+2] = b;
dst[dstOff+3] = a + alphaFac*(255-a);
  • We set the red, green, and blue channels of the output pixel to our weighted sums.
  • For the alpha channel: if opaque is true (alphaFac=1), we compute a + 1*(255 - a) which simplifies to 255—forcing full opacity. If opaque is false, alphaFac=0, so we just use the weighted alpha sum we calculated.

3. Return the Blurred Result

return output;

Finally, we return the ImageData object with our blurred image. You can draw this to a canvas using ctx.putImageData(output, 0, 0) to see the effect.

Quick Example for Blur

If you pass a 3x3 blur matrix like [1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9, 1/9], each output pixel is just the average of the 3x3 grid around the source pixel. This averages out small details, creating that classic soft blur.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:30:09