Heim  >  Artikel  >  Backend-Entwicklung  >  Die Implementierung der Gaußschen Unschärfe führt zu einer seltsamen Ausgabe

Die Implementierung der Gaußschen Unschärfe führt zu einer seltsamen Ausgabe

WBOY
WBOYnach vorne
2024-02-11 09:20:081190Durchsuche

Die Implementierung der Gaußschen Unschärfe führt zu einer seltsamen Ausgabe

php-Redakteur Yuzai wies darauf hin, dass die Gaußsche Unschärfe eine gängige Bildverarbeitungstechnik ist, die Bilder verwischen kann und häufig zum Verschönern von Fotos oder zum Erzielen von Spezialeffekten verwendet wird. Wenn der Gaußsche Unschärfealgorithmus jedoch nicht korrekt implementiert wird, kann es zu seltsamen Ergebnissen kommen. Dazu können Probleme wie Bildverzerrungen, unscharfe Kanten oder Farbverschiebungen gehören. Daher muss bei der Verwendung der Gaußschen Unschärfetechnologie auf die korrekte Implementierung des Algorithmus geachtet werden, um den erwarteten Ausgabeeffekt sicherzustellen.

Frageninhalt

Ich versuche, Gaußsche Unschärfe auf Golang-Objekten zu implementieren. Für die folgenden Bilder: image.image

Das generierte Ausgabebild ist:

Wie man sehen kann, enthält das Ausgabebild einige unverarbeitete Grenzen, die der aktuellen Implementierungsentscheidung entsprechen, Kanten nicht zu verarbeiten, was mich denken lässt, dass ich die Berechnung irgendwie durcheinander gebracht habe (ich meine, dieser Teil der Implementierung funktioniert). sodass ich den einzelnen Fehler beim Durchlaufen von Bildpixeln verwerfen kann. Ich habe diesen Code mehrmals überprüft, kann meinen Fehler jedoch nicht finden. Ich würde mich sehr über Hilfe und Überlegungen bei der Implementierung freuen, die mir bei der Lösung meines Problems helfen könnten. Der Code ist unten enthalten. Wenn Änderungen oder Klarstellungen erforderlich sind, lassen Sie es mich bitte wissen!

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

Bearbeiten

    Ich habe den Code so geändert, dass er die Pixel vom Originalbild statt von
  • rgbaimg liest
  • Ich habe den Kernel auch anhand von
  • Variablenapplygaussianfunction 函数注释了 efactor,因为我已经使用 sum normalisiert
  • Modifizierte
  • Methode zur Verwendung der 64-Bit-RGBA-Struktur.set
Dies ist das neu generierte Bild

Diese schwarzen Ränder lassen sich leicht reparieren, ich bin bereits dabei, sie zu reparieren. Das ist nicht mehr Teil des Problems.

Workaround

Sie lesen aus demselben Bild, an das Sie schreiben. Sie sollten vom Originalbild lesen:

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

Herausgeber: Außerdem : 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)});

Das obige ist der detaillierte Inhalt vonDie Implementierung der Gaußschen Unschärfe führt zu einer seltsamen Ausgabe. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen