Rumah  >  Artikel  >  pembangunan bahagian belakang  >  Pelaksanaan kabur Gaussian menghasilkan output pelik

Pelaksanaan kabur Gaussian menghasilkan output pelik

WBOY
WBOYke hadapan
2024-02-11 09:20:081245semak imbas

Pelaksanaan kabur Gaussian menghasilkan output pelik

editor php Yuzai menegaskan bahawa Gaussian blur ialah teknik pemprosesan imej biasa yang boleh mengaburkan imej dan sering digunakan untuk mencantikkan foto atau mencapai kesan khas. Walau bagaimanapun, jika algoritma kabur Gaussian tidak dilaksanakan dengan betul, ia boleh menghasilkan output yang pelik. Ini mungkin termasuk isu seperti herotan imej, tepi kabur atau peralihan warna. Oleh itu, apabila menggunakan teknologi kabur Gaussian, perhatian mesti diberikan kepada pelaksanaan algoritma yang betul untuk memastikan kesan output yang dijangkakan.

Kandungan soalan

Saya cuba melaksanakan Gaussian blur pada objek golang image.image. Untuk gambar berikut:

Imej keluaran yang dihasilkan ialah:

Seperti yang dapat dilihat, imej output mengandungi beberapa sempadan yang tidak diproses yang sepadan dengan keputusan pelaksanaan semasa untuk tidak memproses tepi, yang membuatkan saya berfikir bahawa saya mungkin telah mengacaukan pengiraan dalam beberapa cara (maksud saya, Bahagian pelaksanaan ini berfungsi jadi saya boleh membuang ralat satu demi satu apabila melelaran pada piksel imej). Saya telah menyemak kod ini beberapa kali tetapi saya tidak menemui ralat saya. Saya amat menghargai bantuan dan pertimbangan mengenai pelaksanaan, yang boleh membantu saya menyelesaikan masalah saya. Kod disertakan di bawah. Jika sebarang suntingan atau penjelasan diperlukan, sila beritahu saya!

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

Edit

  • Saya mengubah suai kod supaya ia membaca piksel daripada imej asal dan bukannya daripada rgbaimg
  • Saya juga menormalkan kernel daripada applygaussianfunction 函数注释了 efactor,因为我已经使用 sum pembolehubah
  • Ubahsuai .set kaedah untuk menggunakan struktur rgba 64-bit

Ini ialah imej yang baru dijana

Sempadan hitam itu mudah dibaiki, saya sudah membetulkannya. Ini bukan lagi sebahagian daripada masalah.

Penyelesaian

Anda membaca dari imej yang sama yang anda tulis. Anda harus membaca dari imej asal:

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

Editor: Selain itu, 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)});

Atas ialah kandungan terperinci Pelaksanaan kabur Gaussian menghasilkan output pelik. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Artikel ini dikembalikan pada:stackoverflow.com. Jika ada pelanggaran, sila hubungi admin@php.cn Padam