func diffOp(mag, dir *image.Gray, src image.Image, opX, opY *convolve.SeparableKernel) error { if src == nil { return errors.New("graphics: src is nil") } b := src.Bounds() srcg, ok := src.(*image.Gray) if !ok { srcg = image.NewGray(b) draw.Draw(srcg, b, src, b.Min, draw.Src) } mx := image.NewGray(b) if err := convolve.Convolve(mx, srcg, opX); err != nil { return err } my := image.NewGray(b) if err := convolve.Convolve(my, srcg, opY); err != nil { return err } for y := b.Min.Y; y < b.Max.Y; y++ { for x := b.Min.X; x < b.Max.X; x++ { off := (y-mx.Rect.Min.Y)*mx.Stride + (x-mx.Rect.Min.X)*1 cx := float64(mx.Pix[off]) cy := float64(my.Pix[off]) if mag != nil { off = (y-mag.Rect.Min.Y)*mag.Stride + (x-mag.Rect.Min.X)*1 mag.Pix[off] = uint8(math.Sqrt(cx*cx + cy*cy)) } if dir != nil { off = (y-dir.Rect.Min.Y)*dir.Stride + (x-dir.Rect.Min.X)*1 angle := math.Atan(cy / cx) // Round the angle to 0, 45, 90, or 135 degrees. angle = math.Mod(angle, 2*math.Pi) var degree uint8 if angle <= math.Pi/8 { degree = 0 } else if angle <= math.Pi*3/8 { degree = 45 } else if angle <= math.Pi*5/8 { degree = 90 } else if angle <= math.Pi*7/8 { degree = 135 } else { degree = 0 } dir.Pix[off] = degree } } } return nil }
// Blur produces a blurred version of the image, using a Gaussian blur. func Blur(dst draw.Image, src image.Image, opt *BlurOptions) error { if dst == nil { return errors.New("graphics: dst is nil") } if src == nil { return errors.New("graphics: src is nil") } sd := DefaultStdDev size := 0 if opt != nil { sd = opt.StdDev size = opt.Size } if size < 1 { size = int(math.Ceil(sd * 6)) } kernel := make([]float64, 2*size+1) for i := 0; i <= size; i++ { x := float64(i) / sd x = math.Pow(1/math.SqrtE, x*x) kernel[size-i] = x kernel[size+i] = x } // Normalize the weights to sum to 1.0. kSum := 0.0 for _, k := range kernel { kSum += k } for i, k := range kernel { kernel[i] = k / kSum } return convolve.Convolve(dst, src, &convolve.SeparableKernel{ X: kernel, Y: kernel, }) }
// LaplacianOfGaussian approximates a 2D laplacian of gaussian with a convolution kernel. func LaplacianOfGaussian(dst *image.Gray, src image.Image) { srcg, ok := src.(*image.Gray) if !ok { b := src.Bounds() srcg = image.NewGray(b) draw.Draw(srcg, b, src, b.Min, draw.Src) } k, err := convolve.NewKernel([]float64{ 0, 0, 1, 0, 0, 0, 1, 2, 1, 0, 1, 2, -16, 2, 1, 0, 1, 2, 1, 0, 0, 0, 1, 0, 0, }) if err != nil { panic(err) // impossible } convolve.Convolve(dst, srcg, k) }