github.com/aloncn/graphics-go@v0.0.1/graphics/detect/integral.go (about) 1 // Copyright 2011 The Graphics-Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package detect 6 7 import ( 8 "image" 9 "image/draw" 10 ) 11 12 // integral is an image.Image-like structure that stores the cumulative 13 // sum of the preceding pixels. This allows for O(1) summation of any 14 // rectangular region within the image. 15 type integral struct { 16 // pix holds the cumulative sum of the image's pixels. The pixel at 17 // (x, y) starts at pix[(y-rect.Min.Y)*stride + (x-rect.Min.X)*1]. 18 pix []uint64 19 stride int 20 rect image.Rectangle 21 } 22 23 func (p *integral) at(x, y int) uint64 { 24 return p.pix[(y-p.rect.Min.Y)*p.stride+(x-p.rect.Min.X)] 25 } 26 27 func (p *integral) sum(b image.Rectangle) uint64 { 28 c := p.at(b.Max.X-1, b.Max.Y-1) 29 inY := b.Min.Y > p.rect.Min.Y 30 inX := b.Min.X > p.rect.Min.X 31 if inY && inX { 32 c += p.at(b.Min.X-1, b.Min.Y-1) 33 } 34 if inY { 35 c -= p.at(b.Max.X-1, b.Min.Y-1) 36 } 37 if inX { 38 c -= p.at(b.Min.X-1, b.Max.Y-1) 39 } 40 return c 41 } 42 43 func (m *integral) integrate() { 44 b := m.rect 45 for y := b.Min.Y; y < b.Max.Y; y++ { 46 for x := b.Min.X; x < b.Max.X; x++ { 47 c := uint64(0) 48 if y > b.Min.Y && x > b.Min.X { 49 c += m.at(x-1, y) 50 c += m.at(x, y-1) 51 c -= m.at(x-1, y-1) 52 } else if y > b.Min.Y { 53 c += m.at(b.Min.X, y-1) 54 } else if x > b.Min.X { 55 c += m.at(x-1, b.Min.Y) 56 } 57 m.pix[(y-m.rect.Min.Y)*m.stride+(x-m.rect.Min.X)] += c 58 } 59 } 60 } 61 62 // newIntegrals returns the integral and the squared integral. 63 func newIntegrals(src image.Image) (*integral, *integral) { 64 b := src.Bounds() 65 srcg, ok := src.(*image.Gray) 66 if !ok { 67 srcg = image.NewGray(b) 68 draw.Draw(srcg, b, src, b.Min, draw.Src) 69 } 70 71 m := integral{ 72 pix: make([]uint64, b.Max.Y*b.Max.X), 73 stride: b.Max.X, 74 rect: b, 75 } 76 mSq := integral{ 77 pix: make([]uint64, b.Max.Y*b.Max.X), 78 stride: b.Max.X, 79 rect: b, 80 } 81 for y := b.Min.Y; y < b.Max.Y; y++ { 82 for x := b.Min.X; x < b.Max.X; x++ { 83 os := (y-b.Min.Y)*srcg.Stride + x - b.Min.X 84 om := (y-b.Min.Y)*m.stride + x - b.Min.X 85 c := uint64(srcg.Pix[os]) 86 m.pix[om] = c 87 mSq.pix[om] = c * c 88 } 89 } 90 m.integrate() 91 mSq.integrate() 92 return &m, &mSq 93 }