Beispiel #1
0
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
}
Beispiel #2
0
// 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,
	})
}
Beispiel #3
0
// 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)
}