php小編魚仔指出,高斯模糊是一種常用的影像處理技術,可以使影像變得模糊,常用於美化照片或實現特效。然而,如果不正確地實現高斯模糊演算法,可能會產生奇怪的輸出。這可能包括影像失真、邊緣模糊或色彩偏移等問題。因此,在使用高斯模糊技術時,必須注意演算法的正確實現,以確保獲得預期的輸出效果。
我正在嘗試在 golang image.image
物件上實作高斯模糊。對於以下圖像:
產生的輸出影像為:
正如人們所看到的,輸出圖像包含一些未處理的邊界,這些邊界對應於當前不處理邊緣的實現決策,這讓我認為我可能在某種程度上搞砸了計算(我的意思是,這部分實現的工作原理,因此我可以在迭代圖像像素時丟棄差一錯誤)。我已經多次檢查了這段程式碼,但我找不到我的錯誤。我非常感謝有關實施的一些幫助和考慮,這可以幫助我解決問題。程式碼包含在下面。如果需要任何編輯或澄清,請告訴我!
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; }
編輯
rgbaimg
applygaussianfunction
函數註解了 efactor
,因為我已經使用 sum
變數規範化核心.set
方法以使用 64 位元 rgba 結構這是新生成的圖片
那些黑色邊框很容易解決,我已經在解決它們了。這不再是問題的一部分。
您正在從正在寫入的相同映像中讀取內容。您應該從原始圖像中讀取:
pr, pg, pb, pa := img.at(x+j, y+i).rgba()
編輯:
此外, 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)});
以上是高斯模糊實作會產生奇怪的輸出的詳細內容。更多資訊請關注PHP中文網其他相關文章!