Maison  >  Article  >  développement back-end  >  L'implémentation du flou gaussien produit un résultat étrange

L'implémentation du flou gaussien produit un résultat étrange

WBOY
WBOYavant
2024-02-11 09:20:081187parcourir

Limplémentation du flou gaussien produit un résultat étrange

L'éditeur php Yuzai a souligné que le flou gaussien est une technologie de traitement d'image courante qui peut rendre les images floues et est souvent utilisée pour embellir des photos ou obtenir des effets spéciaux. Cependant, si l’algorithme de flou gaussien n’est pas implémenté correctement, il peut produire un résultat étrange. Cela peut inclure des problèmes tels qu'une distorsion de l'image, des bords flous ou des changements de couleur. Par conséquent, lors de l’utilisation de la technologie du flou gaussien, il faut prêter attention à la mise en œuvre correcte de l’algorithme pour garantir l’effet de sortie attendu.

Contenu de la question

J'essaie d'implémenter le flou gaussien sur des objets Golang image.image. Pour les images suivantes :

L'image de sortie générée est :

Comme on peut le voir, l'image de sortie contient des limites non traitées qui correspondent à la décision actuelle d'implémentation de ne pas traiter les bords, ce qui me fait penser que j'ai peut-être gâché le calcul d'une manière ou d'une autre (je veux dire, cette partie de l'implémentation fonctionne afin que je puisse supprimer l'erreur une par une lors de l'itération sur les pixels de l'image). J'ai vérifié ce code plusieurs fois mais je ne trouve pas mon erreur. J'apprécierais vraiment de l'aide et de la considération sur la mise en œuvre, ce qui pourrait m'aider à résoudre mon problème. Le code est inclus ci-dessous. Si des modifications ou des clarifications sont nécessaires, faites-le-moi savoir !

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;
}

Modifier

  • J'ai modifié le code pour qu'il lise les pixels de l'image originale au lieu de rgbaimg
  • J'ai également normalisé le noyau à partir de applygaussianfunction 函数注释了 efactor,因为我已经使用 sum variables
  • Méthode .set modifiée pour utiliser la structure rgba 64 bits

Voici l'image nouvellement générée

Ces bordures noires sont faciles à corriger, je suis déjà en train de les réparer. Cela ne fait plus partie du problème.

Solution de contournement

Vous lisez à partir de la même image sur laquelle vous écrivez. Vous devriez lire à partir de l'image originale :

pr, pg, pb, pa := img.at(x+j, y+i).rgba()

Éditeur : De plus, image.at 返回 color.rgba,而 func (color.rgba) rgba 返回0 到 0xffff 范围。然而 color.rgba 构造函数期望它们在 0 到 255 范围内。在写入结果时,您可能需要使用 color.rgba64 :

rgbaImg.Set(x, y, color.RGBA64{uint16(nr), uint16(ng), uint16(nb), uint16(na)});

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Cet article est reproduit dans:. en cas de violation, veuillez contacter admin@php.cn Supprimer