Maison > développement back-end > Golang > le corps du texte

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

WBOY
Libérer: 2024-02-11 09:20:08
avant
1249 Les gens l'ont consulté

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;
}
Copier après la connexion

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()
Copier après la connexion

É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)});
Copier après la connexion

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!

Étiquettes associées:
source:stackoverflow.com
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal