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

Golang中image.Image的Gaussian Blur实现异常输出问题排查

Go实现高斯模糊的问题排查与修改

问题背景

我正在尝试用Go语言对image.Image对象实现高斯模糊效果:

  • 原始图像:原始图像
  • 最初生成的模糊图像:初始模糊结果

输出图像存在未处理的边框,这对应当前实现中不处理边缘的逻辑,但我怀疑计算环节存在错误(已排除像素遍历的偏移错误)。多次检查代码仍未找到问题,遂附上实现代码寻求帮助。

后续修改

之后我对代码做了以下调整:

  • 修改为从原始图像读取像素,而非转换后的rgbaImg
  • 注释掉applyGaussianFunction中的eFactor,因为已通过sum变量对核进行归一化
  • 修改Set方法使用64位RGBA结构体(color.RGBA64)

修改后生成的图像:修改后的模糊输出,目前黑边问题已在解决中,不再是当前核心问题。

实现代码

package main

import (
    "image"
    "image/color"
    "image/draw"
    "image/jpeg"
    "math"
    "os"
)

func main() {
    f, err := os.Open("dog.jpeg")
    if err != nil {
        panic(err)
    }

    img, err := jpeg.Decode(f)
    if err != nil {
        panic(err)
    }

    newImg := gaussianBlur(img, 3)

    out, err := os.Create("dog-blurred.jpeg")
    if err != nil {
        panic(err)
    }

    err = jpeg.Encode(out, newImg, nil)
    if err != nil {
        panic(err)
    }
}

func applyGaussianFunction(x, y, stdDev float64) float64 {
    // eFactor := 1 / (2 * math.Pi * stdDev*stdDev);
    ePowNominator := -(x*x + y*y);
    ePowDenominator := 2 * stdDev*stdDev;

    return math.Pow(math.E, (ePowNominator/ePowDenominator));
}

func generateKernel(radius int) [][]float64 {
    size := 1 + (radius * 2);
    kernel := make([][]float64, size);
    stdDev := math.Max(float64(radius / 2), 1);

    sum := float64(0);

    for i := 0; i < size; i++ {
        kernel[i] = make([]float64, size);
    }

    for i := -radius; i < radius + 1; i++ {
        for j := -radius; j < radius + 1; j++ {
            val := applyGaussianFunction(float64(j), float64(i), stdDev);
            kernel[i + radius][j + radius] = val;
            sum += val;
        }
    }

    for i := 0; i < size; i++ {
        for j := 0; j < size; j++ {
            kernel[i][j] /= sum;
        }
    }

    return kernel;
}

func makeImageRGBA(src image.Image) *image.RGBA {
    b := src.Bounds().Size();
    rgba := image.NewRGBA(image.Rect(0, 0, b.X, b.Y));
    draw.Draw(rgba, rgba.Bounds(), src, image.Pt(0, 0), draw.Src);

    return rgba;
}

func gaussianBlur(img image.Image, radius int) image.Image {
    size := img.Bounds().Size();
    rgbaImg := image.NewRGBA(image.Rect(0, 0, size.X, size.Y));

    kernel := generateKernel(radius);

    for y := radius; y < size.Y - radius; y++ {
        for x := radius; x < size.X - radius; x++ {
            var nr, ng, nb, na float64 = 0, 0, 0, 0;

            for i := -radius; i < radius + 1; i++ {
                for j := -radius; j < radius + 1; j++ {
                    // NEW: Get pixels from original Image
                    pr, pg, pb, pa := img.At(x - j, y - i).RGBA();

                    nr += float64(pr) * kernel[i + radius][j + radius];
                    ng += float64(pg) * kernel[i + radius][j + radius];
                    nb += float64(pb) * kernel[i + radius][j + radius];
                    na += float64(pa) * kernel[i + radius][j + radius];
                }
            }

            // Handle overflow by using 64-bit alphapremultiplied values
            rgbaImg.Set(x, y, color.RGBA64{uint16(nr), uint16(ng), uint16(nb), uint16(na)});
        }
    }

    return rgbaImg;
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.05 08:50:45