From 87509aed1156cfb93a48a1a8e0dbea94661f3994 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Tue, 28 Jan 2020 16:04:18 +1030 Subject: [PATCH] optimising --- filter/basic.go | 98 ++++++++++++++++++++++++++++++------------------- filter/mog.go | 9 ++--- 2 files changed, 63 insertions(+), 44 deletions(-) diff --git a/filter/basic.go b/filter/basic.go index 6175f823..9657874b 100644 --- a/filter/basic.go +++ b/filter/basic.go @@ -43,16 +43,25 @@ import ( "golang.org/x/image/math/fixed" ) +func absDiff(a, b uint32) int { + c := int(a) - int(b) + if c < 0 { + return -c + } else { + return c + } + +} + // MOGFilter is a filter that provides basic motion detection. MoG is short for // Mixture of Gaussians method. type BasicFilter struct { - dst io.WriteCloser - bg [][][3]uint32 - current [][][3]uint32 - w int - h int - file io.WriteCloser - debug bool + dst io.WriteCloser + bg [][][3]uint32 + w int + h int + file io.WriteCloser + debug bool } // NewMOGFilter returns a pointer to a new MOGFilter struct. @@ -68,7 +77,7 @@ func NewBasicFilter(dst io.WriteCloser, debug bool) *BasicFilter { file = nil } - return &BasicFilter{dst, nil, nil, 0, 0, file, debug} + return &BasicFilter{dst, nil, 0, 0, file, debug} } // Implements io.Closer. @@ -82,7 +91,7 @@ func (m *BasicFilter) Close() error { // Write applies the motion filter to the video stream. Only frames with motion // are written to the destination encoder, frames without are discarded. func (b *BasicFilter) Write(f []byte) (int, error) { - //t0 := time.Now() + t0 := time.Now() //decode MJPEG r := bytes.NewReader(f) img, err := jpeg.Decode(r) @@ -103,20 +112,13 @@ func (b *BasicFilter) Write(f []byte) (int, error) { b.bg[i] = make([][3]uint32, b.w) } - b.current = make([][][3]uint32, b.h) - for i, _ := range b.current { - b.current[i] = make([][3]uint32, b.w) - } - for j := 0; j < b.h; j++ { for i := 0; i < b.w; i++ { n := img.At(i, j) R, G, B, _ := n.RGBA() - b.bg[j][i] = [3]uint32{R, G, B} + copy(b.bg[j][i][:], []uint32{R, G, B}) } } - t2 := time.Now() - fmt.Print("BG loop: ", t2.Sub(t1).Milliseconds(), "\n") return len(f), nil } @@ -126,28 +128,49 @@ func (b *BasicFilter) Write(f []byte) (int, error) { bwImg := image.NewRGBA(image.Rect(0, 0, b.w, b.h)) for j := 0; j < b.h; j++ { for i := 0; i < b.w; i++ { + // ti0 := time.Now() n := img.At(i, j) + // ti1 := time.Now() R, G, B, _ := n.RGBA() - b.current[j][i] = [3]uint32{R, G, B} - - diffR := R - b.bg[j][i][0] - diffG := G - b.bg[j][i][1] - diffB := B - b.bg[j][i][2] - + // ti2 := time.Now() // diffR := int(math.Abs(float64(R) - float64(b.bg[j][i][0]))) // diffG := int(math.Abs(float64(G) - float64(b.bg[j][i][1]))) // diffB := int(math.Abs(float64(B) - float64(b.bg[j][i][2]))) + + diffB := absDiff(B, b.bg[j][i][2]) + diffR := absDiff(R, b.bg[j][i][0]) + diffG := absDiff(G, b.bg[j][i][1]) + + // ti3 := time.Now() + diff := diffR + diffG + diffB - if diff < 45000 && b.debug { - bwImg.SetRGBA(i, j, color.RGBA{0x00, 0x00, 0x00, 0xff}) - } else { - bwImg.SetRGBA(i, j, color.RGBA{0xff, 0xff, 0xff, 0xff}) + if diff > 45000 { motion++ } + + if b.debug { + if diff > 45000 { + bwImg.SetRGBA(i, j, color.RGBA{0xff, 0xff, 0xff, 0xff}) + } else { + bwImg.SetRGBA(i, j, color.RGBA{0x00, 0x00, 0x00, 0xff}) + } + } + // ti4 := time.Now() + // Update backgound image. + copy(b.bg[j][i][:], []uint32{R, G, B}) + // ti5 := time.Now() + + // fmt.Print("At: ", ti1.Sub(ti0).Nanoseconds(), "\n") + // fmt.Print("RGBA: ", ti2.Sub(ti1).Nanoseconds(), "\n") + // fmt.Print("3x absDiff: ", ti3.Sub(ti2).Nanoseconds(), "\n") + // fmt.Print("total diff + threshold + debug: ", ti4.Sub(ti3).Nanoseconds(), "\n") + // fmt.Print("update bg: ", ti5.Sub(ti4).Nanoseconds(), "\n") + // fmt.Print("Total: ", time.Now().Sub(ti0).Nanoseconds(), "\n\n") } } - //t3 := time.Now() + t2 := time.Now() + //visualise if b.debug { col := color.RGBA{200, 100, 0, 255} @@ -165,20 +188,19 @@ func (b *BasicFilter) Write(f []byte) (int, error) { return len(f), err } } - //t4 := time.Now() - // //update backgound image - b.bg = b.current - //get mean of this difference + t3 := time.Now() + + fmt.Print("Encode: ", t1.Sub(t0).Milliseconds(), "\n") + fmt.Print("Calc loop: ", t2.Sub(t1).Milliseconds(), "\n") + fmt.Print("VLC: ", t3.Sub(t2).Milliseconds(), "\n") + fmt.Print("Total: ", time.Now().Sub(t0).Milliseconds(), "\n\n") //choose a threshold that motion is detected for if greater - + if motion < 1000 { + return len(f), nil + } //discard non motion frames //write motion frames - // fmt.Print("Encode: ", t1.Sub(t0).Milliseconds(), "\n") - // fmt.Print("BG loop: ", t2.Sub(t1).Milliseconds(), "\n") - // fmt.Print("Calc loop: ", t3.Sub(t2).Milliseconds(), "\n") - // fmt.Print("VLC: ", t4.Sub(t3).Milliseconds(), "\n") - // fmt.Print("Total: ", time.Now().Sub(t0).Milliseconds(), "\n\n") return b.dst.Write(f) } diff --git a/filter/mog.go b/filter/mog.go index e5aa2927..20fd5807 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -33,7 +33,6 @@ import ( "image" "image/color" "io" - "time" "gocv.io/x/gocv" ) @@ -79,7 +78,6 @@ func (m *MOGFilter) Close() error { // Write applies the motion filter to the video stream. Only frames with motion // are written to the destination encoder, frames without are discarded. func (m *MOGFilter) Write(f []byte) (int, error) { - t0 := time.Now() if m.hfCount < (m.hf - 1) { m.hold[m.hfCount] = f m.hfCount++ @@ -136,9 +134,9 @@ func (m *MOGFilter) Write(f []byte) (int, error) { } // Don't write to destination if there is no motion. - // if len(contours) == 0 { - // return len(f), nil - // } + if len(contours) == 0 { + return len(f), nil + } // Write to destination, past 4 frames then current frame. for i, h := range m.hold { @@ -148,6 +146,5 @@ func (m *MOGFilter) Write(f []byte) (int, error) { return len(f), fmt.Errorf("could not write previous frames: %w", err) } } - fmt.Print(time.Now().Sub(t0).Milliseconds(), "\n") return m.dst.Write(f) }