Example #1
0
// Canny detects and returns edges from the given image.
// Each dst pixel is given one of three values:
//   0xff: an edge
//   0x80: possibly an edge
//   0x00: not an edge
func Canny(dst *image.Gray, src image.Image) error {
	if dst == nil {
		return errors.New("edge: dst is nil")
	}
	if src == nil {
		return errors.New("edge: src is nil")
	}

	b := src.Bounds()
	srcGray, ok := src.(*image.Gray)
	if !ok {
		srcGray = image.NewGray(b)
		draw.Draw(srcGray, b, src, b.Min, draw.Src)
	}

	if err := graphics.Blur(srcGray, srcGray, nil); err != nil {
		return err
	}

	mag, dir := image.NewGray(b), image.NewGray(b)
	if err := Sobel(mag, dir, srcGray); err != nil {
		return err
	}

	// Non-maximum supression.
	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			d := dir.Pix[(y-b.Min.Y)*dir.Stride+(x-b.Min.X)*1]
			var m0, m1 uint8
			switch d {
			case 0: // west and east
				m0 = atOrZero(mag, x-1, y)
				m1 = atOrZero(mag, x+1, y)
			case 45: // north-east and south-west
				m0 = atOrZero(mag, x+1, y-1)
				m1 = atOrZero(mag, x-1, y+1)
			case 90: // north and south
				m0 = atOrZero(mag, x, y-1)
				m1 = atOrZero(mag, x, y+1)
			case 135: // north-west and south-east
				m0 = atOrZero(mag, x-1, y-1)
				m1 = atOrZero(mag, x+1, y+1)
			default:
				return fmt.Errorf("edge: bad direction (%d, %d): %d", x, y, d)
			}

			m := mag.Pix[(y-b.Min.Y)*mag.Stride+(x-b.Min.X)*1]
			if m > m0 && m > m1 {
				m = 0xff
			} else if m > m0 || m > m1 {
				m = 0x80
			} else {
				m = 0x00
			}
			dst.Pix[(y-b.Min.Y)*dst.Stride+(x-b.Min.X)*1] = m
		}
	}

	return nil
}
Example #2
0
// DifferenceOfGaussians produces the difference of Gaussians sd0 and sd1.
func DifferenceOfGaussians(dst *image.Gray, src image.Image, sd0, sd1 float64) {
	b := src.Bounds()
	srcg := image.NewGray(b)
	m0 := image.NewGray(b)
	m1 := image.NewGray(b)

	draw.Draw(srcg, b, src, b.Min, draw.Src)

	graphics.Blur(m0, srcg, &graphics.BlurOptions{StdDev: sd0})
	graphics.Blur(m1, srcg, &graphics.BlurOptions{StdDev: sd1})

	for y := b.Min.Y; y < b.Max.Y; y++ {
		for x := b.Min.X; x < b.Max.X; x++ {
			off := (y-m0.Rect.Min.Y)*m0.Stride + (x - m0.Rect.Min.X)
			c := m0.Pix[off] - m1.Pix[off]
			if c < 0 {
				c = -c
			}

			doff := (y-dst.Rect.Min.Y)*dst.Stride + (x - dst.Rect.Min.X)
			dst.Pix[doff] = c
		}
	}
}