mirror of https://bitbucket.org/ausocean/av.git
optimising
This commit is contained in:
parent
ed35bd83cb
commit
87509aed11
|
@ -43,16 +43,25 @@ import (
|
||||||
"golang.org/x/image/math/fixed"
|
"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
|
// MOGFilter is a filter that provides basic motion detection. MoG is short for
|
||||||
// Mixture of Gaussians method.
|
// Mixture of Gaussians method.
|
||||||
type BasicFilter struct {
|
type BasicFilter struct {
|
||||||
dst io.WriteCloser
|
dst io.WriteCloser
|
||||||
bg [][][3]uint32
|
bg [][][3]uint32
|
||||||
current [][][3]uint32
|
w int
|
||||||
w int
|
h int
|
||||||
h int
|
file io.WriteCloser
|
||||||
file io.WriteCloser
|
debug bool
|
||||||
debug bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewMOGFilter returns a pointer to a new MOGFilter struct.
|
// NewMOGFilter returns a pointer to a new MOGFilter struct.
|
||||||
|
@ -68,7 +77,7 @@ func NewBasicFilter(dst io.WriteCloser, debug bool) *BasicFilter {
|
||||||
file = nil
|
file = nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return &BasicFilter{dst, nil, nil, 0, 0, file, debug}
|
return &BasicFilter{dst, nil, 0, 0, file, debug}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements io.Closer.
|
// 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
|
// Write applies the motion filter to the video stream. Only frames with motion
|
||||||
// are written to the destination encoder, frames without are discarded.
|
// are written to the destination encoder, frames without are discarded.
|
||||||
func (b *BasicFilter) Write(f []byte) (int, error) {
|
func (b *BasicFilter) Write(f []byte) (int, error) {
|
||||||
//t0 := time.Now()
|
t0 := time.Now()
|
||||||
//decode MJPEG
|
//decode MJPEG
|
||||||
r := bytes.NewReader(f)
|
r := bytes.NewReader(f)
|
||||||
img, err := jpeg.Decode(r)
|
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.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 j := 0; j < b.h; j++ {
|
||||||
for i := 0; i < b.w; i++ {
|
for i := 0; i < b.w; i++ {
|
||||||
n := img.At(i, j)
|
n := img.At(i, j)
|
||||||
R, G, B, _ := n.RGBA()
|
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
|
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))
|
bwImg := image.NewRGBA(image.Rect(0, 0, b.w, b.h))
|
||||||
for j := 0; j < b.h; j++ {
|
for j := 0; j < b.h; j++ {
|
||||||
for i := 0; i < b.w; i++ {
|
for i := 0; i < b.w; i++ {
|
||||||
|
// ti0 := time.Now()
|
||||||
n := img.At(i, j)
|
n := img.At(i, j)
|
||||||
|
// ti1 := time.Now()
|
||||||
R, G, B, _ := n.RGBA()
|
R, G, B, _ := n.RGBA()
|
||||||
b.current[j][i] = [3]uint32{R, G, B}
|
// ti2 := time.Now()
|
||||||
|
|
||||||
diffR := R - b.bg[j][i][0]
|
|
||||||
diffG := G - b.bg[j][i][1]
|
|
||||||
diffB := B - b.bg[j][i][2]
|
|
||||||
|
|
||||||
// diffR := int(math.Abs(float64(R) - float64(b.bg[j][i][0])))
|
// diffR := int(math.Abs(float64(R) - float64(b.bg[j][i][0])))
|
||||||
// diffG := int(math.Abs(float64(G) - float64(b.bg[j][i][1])))
|
// 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 := 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
|
diff := diffR + diffG + diffB
|
||||||
|
|
||||||
if diff < 45000 && b.debug {
|
if diff > 45000 {
|
||||||
bwImg.SetRGBA(i, j, color.RGBA{0x00, 0x00, 0x00, 0xff})
|
|
||||||
} else {
|
|
||||||
bwImg.SetRGBA(i, j, color.RGBA{0xff, 0xff, 0xff, 0xff})
|
|
||||||
motion++
|
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
|
//visualise
|
||||||
if b.debug {
|
if b.debug {
|
||||||
col := color.RGBA{200, 100, 0, 255}
|
col := color.RGBA{200, 100, 0, 255}
|
||||||
|
@ -165,20 +188,19 @@ func (b *BasicFilter) Write(f []byte) (int, error) {
|
||||||
return len(f), err
|
return len(f), err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//t4 := time.Now()
|
t3 := time.Now()
|
||||||
// //update backgound image
|
|
||||||
b.bg = b.current
|
fmt.Print("Encode: ", t1.Sub(t0).Milliseconds(), "\n")
|
||||||
//get mean of this difference
|
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
|
//choose a threshold that motion is detected for if greater
|
||||||
|
if motion < 1000 {
|
||||||
|
return len(f), nil
|
||||||
|
}
|
||||||
//discard non motion frames
|
//discard non motion frames
|
||||||
|
|
||||||
//write 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)
|
return b.dst.Write(f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import (
|
||||||
"image"
|
"image"
|
||||||
"image/color"
|
"image/color"
|
||||||
"io"
|
"io"
|
||||||
"time"
|
|
||||||
|
|
||||||
"gocv.io/x/gocv"
|
"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
|
// Write applies the motion filter to the video stream. Only frames with motion
|
||||||
// are written to the destination encoder, frames without are discarded.
|
// are written to the destination encoder, frames without are discarded.
|
||||||
func (m *MOGFilter) Write(f []byte) (int, error) {
|
func (m *MOGFilter) Write(f []byte) (int, error) {
|
||||||
t0 := time.Now()
|
|
||||||
if m.hfCount < (m.hf - 1) {
|
if m.hfCount < (m.hf - 1) {
|
||||||
m.hold[m.hfCount] = f
|
m.hold[m.hfCount] = f
|
||||||
m.hfCount++
|
m.hfCount++
|
||||||
|
@ -136,9 +134,9 @@ func (m *MOGFilter) Write(f []byte) (int, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't write to destination if there is no motion.
|
// Don't write to destination if there is no motion.
|
||||||
// if len(contours) == 0 {
|
if len(contours) == 0 {
|
||||||
// return len(f), nil
|
return len(f), nil
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Write to destination, past 4 frames then current frame.
|
// Write to destination, past 4 frames then current frame.
|
||||||
for i, h := range m.hold {
|
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)
|
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)
|
return m.dst.Write(f)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue