From b39a4401051da56082d0d9e987deffc866956999 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Thu, 2 Jan 2020 13:37:06 +1030 Subject: [PATCH 01/18] making mog filter that only dectects motion on every 5 frame (will make this a var) --- filter/mog.go | 118 ++++++++++++++++++++++++----------------- revid/config/config.go | 6 +++ revid/revid.go | 32 +++++++++-- 3 files changed, 103 insertions(+), 53 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 9c647bd2..5a2bb7ad 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -46,17 +46,22 @@ type MOGFilter struct { knl gocv.Mat debug bool windows []*gocv.Window + hold [][]byte + hf int } +var hfCount int = 0 + // NewMOGFilter returns a pointer to a new MOGFilter struct. -func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool) *MOGFilter { +func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int) *MOGFilter { bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false) k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3)) var windows []*gocv.Window if debug { windows = []*gocv.Window{gocv.NewWindow("MOG: Bounding boxes"), gocv.NewWindow("MOG: Motion")} } - return &MOGFilter{dst, area, &bs, k, debug, windows} + hold := make([][]byte, hf-1) + return &MOGFilter{dst, area, &bs, k, debug, windows, hold, hf} } // Implements io.Closer. @@ -75,59 +80,74 @@ 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) { - img, err := gocv.IMDecode(f, gocv.IMReadColor) - if err != nil { - return 0, fmt.Errorf("image can't be decoded: %w", err) - } - defer img.Close() - - imgDelta := gocv.NewMat() - defer imgDelta.Close() - - // Seperate foreground and background. - m.bs.Apply(img, &imgDelta) - - // Threshold imgDelta. - gocv.Threshold(imgDelta, &imgDelta, 25, 255, gocv.ThresholdBinary) - - // Remove noise. - gocv.Erode(imgDelta, &imgDelta, m.knl) - gocv.Dilate(imgDelta, &imgDelta, m.knl) - - // Fill small holes. - gocv.Dilate(imgDelta, &imgDelta, m.knl) - gocv.Erode(imgDelta, &imgDelta, m.knl) - - // Find contours and reject ones with a small area. - var contours [][]image.Point - allContours := gocv.FindContours(imgDelta, gocv.RetrievalExternal, gocv.ChainApproxSimple) - for _, c := range allContours { - if gocv.ContourArea(c) > m.area { - contours = append(contours, c) + if hfCount < (m.hf - 1) { + m.hold[hfCount] = f + hfCount++ + return -1, nil + } else { + img, err := gocv.IMDecode(f, gocv.IMReadColor) + if err != nil { + return 0, fmt.Errorf("image can't be decoded: %w", err) } - } + defer img.Close() - // Draw debug information. - if m.debug { - for _, c := range contours { - rect := gocv.BoundingRect(c) - gocv.Rectangle(&img, rect, color.RGBA{0, 0, 255, 0}, 1) + imgDelta := gocv.NewMat() + defer imgDelta.Close() + + // Seperate foreground and background. + m.bs.Apply(img, &imgDelta) + + // Threshold imgDelta. + gocv.Threshold(imgDelta, &imgDelta, 25, 255, gocv.ThresholdBinary) + + // Remove noise. + gocv.Erode(imgDelta, &imgDelta, m.knl) + gocv.Dilate(imgDelta, &imgDelta, m.knl) + + // Fill small holes. + gocv.Dilate(imgDelta, &imgDelta, m.knl) + gocv.Erode(imgDelta, &imgDelta, m.knl) + + // Find contours and reject ones with a small area. + var contours [][]image.Point + allContours := gocv.FindContours(imgDelta, gocv.RetrievalExternal, gocv.ChainApproxSimple) + for _, c := range allContours { + if gocv.ContourArea(c) > m.area { + contours = append(contours, c) + } } - if len(contours) > 0 { - gocv.PutText(&img, "Motion", image.Pt(32, 32), gocv.FontHersheyPlain, 2.0, color.RGBA{255, 0, 0, 0}, 2) + // Draw debug information. + if m.debug { + for _, c := range contours { + rect := gocv.BoundingRect(c) + gocv.Rectangle(&img, rect, color.RGBA{0, 0, 255, 0}, 1) + } + + if len(contours) > 0 { + gocv.PutText(&img, "Motion", image.Pt(32, 32), gocv.FontHersheyPlain, 2.0, color.RGBA{255, 0, 0, 0}, 2) + } + + m.windows[0].IMShow(img) + m.windows[1].IMShow(imgDelta) + m.windows[0].WaitKey(1) } - m.windows[0].IMShow(img) - m.windows[1].IMShow(imgDelta) - m.windows[0].WaitKey(1) + // Don't write to destination if there is no motion. + if len(contours) == 0 { + return 0, nil + } + + // Write to destination, past 4 frames then current frame. + for _, h := range m.hold { + _, err := m.dst.Write(h) + if err != nil { + return 0, err + } + } + + hfCount = 0 + return m.dst.Write(f) } - // Don't write to destination if there is no motion. - if len(contours) == 0 { - return 0, nil - } - - // Write to destination. - return m.dst.Write(f) } diff --git a/revid/config/config.go b/revid/config/config.go index 8768e9db..b37fc759 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -85,6 +85,7 @@ const ( defaultClipDuration = 0 defaultAudioInputCodec = codecutil.ADPCM defaultPSITime = 2 + defaultFilterFrames = 1 // Ring buffer defaults. defaultRBMaxElements = 10000 @@ -275,6 +276,7 @@ type Config struct { HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input. VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input. Filters []int // Defines the methods of filtering to be used in between lexing and encoding. + FilterFrames int // Sets the number of frames that are held before the filter is used (on the nth frame) PSITime int // Sets the time between a packet being sent. // Ring buffer parameters. @@ -460,6 +462,10 @@ func (c *Config) Validate() error { c.Logger.Log(logger.Info, pkg+"PSITime bad or unset, defaulting", "PSITime", defaultPSITime) c.PSITime = defaultPSITime } + if c.FilterFrames <= 0 { + c.Logger.Log(logger.Info, pkg+"FilterFrames bad or unset, defaulting", "FilterFrames", defaultFilterFrames) + c.FilterFrames = defaultFilterFrames + } if c.MinFPS <= 0 { c.Logger.Log(logger.Info, pkg+"MinFPS bad or unset, defaulting", "MinFPS", defaultMinFPS) diff --git a/revid/revid.go b/revid/revid.go index 07c317e4..f5398c72 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -63,6 +63,24 @@ const ( rtmpConnectionTimeout = 10 ) +// Motion filter parameters. +const minFPS = 1.0 + +// KNN specific parameters. +const ( + knnMinArea = 25.0 + knnThreshold = 300 + knnHistory = 300 + knnKernel = 9 +) + +// MOG specific parameters. +const ( + mogMinArea = 50 + mogThreshold = 100 + mogHistory = 100 +) + const pkg = "revid: " type Logger interface { @@ -337,17 +355,16 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. case config.FilterNoOp: r.filters[i] = filter.NewNoOp(dst) case config.FilterMOG: - r.filters[i] = filter.NewMOGFilter(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.ShowWindows) + r.filters[i] = filter.NewMOGFilter(dst, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames) case config.FilterVariableFPS: - r.filters[i] = filter.NewVariableFPSFilter(dst, r.cfg.MinFPS, filter.NewMOGFilter(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.ShowWindows)) + r.filters[i] = filter.NewVariableFPSFilter(dst, minFPS, filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames)) case config.FilterKNN: - r.filters[i] = filter.NewKNNFilter(dst, r.cfg.KNNMinArea, r.cfg.KNNThreshold, int(r.cfg.KNNHistory), int(r.cfg.KNNKernel), r.cfg.ShowWindows) + r.filters[i] = filter.NewKNNFilter(dst, knnMinArea, knnThreshold, knnHistory, knnKernel, r.cfg.ShowWindows) default: panic("Undefined Filter") } dst = r.filters[i] } - } switch r.cfg.Input { @@ -671,6 +688,13 @@ func (r *Revid) Update(vars map[string]string) error { } r.cfg.Filters[i] = v } + case "FilterFrames": + v, err := strconv.Atoi(value) + if err != nil || v < 0 { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid FilterFrames var", "value", value) + break + } + r.cfg.FilterFrames = v case "PSITime": v, err := strconv.Atoi(value) if err != nil || v < 0 { From 6f16f68611e6732303009f23a08f6650ac39f640 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Thu, 2 Jan 2020 14:45:59 +1030 Subject: [PATCH 02/18] adding variable to choose how many frames to skip before filtering --- filter/mog.go | 4 ++-- revid/config/config.go | 8 ++++++++ revid/revid.go | 25 +++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 2 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 5a2bb7ad..cff19d3e 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -139,8 +139,9 @@ func (m *MOGFilter) Write(f []byte) (int, error) { } // Write to destination, past 4 frames then current frame. - for _, h := range m.hold { + for i, h := range m.hold { _, err := m.dst.Write(h) + m.hold[i] = nil if err != nil { return 0, err } @@ -149,5 +150,4 @@ func (m *MOGFilter) Write(f []byte) (int, error) { hfCount = 0 return m.dst.Write(f) } - } diff --git a/revid/config/config.go b/revid/config/config.go index b37fc759..ea1f3b16 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -273,11 +273,19 @@ type Config struct { Width uint // Width defines the input video width Raspivid input. Bitrate uint // Bitrate specifies the bitrate for constant bitrate in kbps. +<<<<<<< HEAD HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input. VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input. Filters []int // Defines the methods of filtering to be used in between lexing and encoding. FilterFrames int // Sets the number of frames that are held before the filter is used (on the nth frame) PSITime int // Sets the time between a packet being sent. +======= + HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input. + VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input. + Filter int // Defines the method of filtering to be used in between lexing and encoding. + FilterFrames int // Sets the number of frames that are held before the filter is used (on the nth frame) + PSITime int // Sets the time between a packet being sent +>>>>>>> d097308e... adding variable to choose how many frames to skip before filtering // Ring buffer parameters. RBMaxElements int // The maximum possible number of elements in ring buffer. diff --git a/revid/revid.go b/revid/revid.go index f5398c72..a375847e 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -344,6 +344,7 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. r.encoders = multiWriter(encoders...) +<<<<<<< HEAD l := len(r.cfg.Filters) r.filters = []filter.Filter{filter.NewNoOp(r.encoders)} if l != 0 { @@ -365,6 +366,20 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. } dst = r.filters[i] } +======= + switch r.cfg.Filter { + case config.FilterNoOp: + r.filter = filter.NewNoOp(r.encoders) + case config.FilterMOG: + r.filter = filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames) + case config.FilterVariableFPS: + r.filter = filter.NewVariableFPSFilter(r.encoders, minFPS, filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames)) + case config.FilterKNN: + r.filter = filter.NewKNNFilter(r.encoders, knnMinArea, knnThreshold, knnHistory, knnKernel, r.cfg.ShowWindows) + + default: + panic("Undefined Filter") +>>>>>>> d097308e... adding variable to choose how many frames to skip before filtering } switch r.cfg.Input { @@ -694,6 +709,16 @@ func (r *Revid) Update(vars map[string]string) error { r.cfg.Logger.Log(logger.Warning, pkg+"invalid FilterFrames var", "value", value) break } +<<<<<<< HEAD +======= + r.cfg.Filter = v + case "FilterFrames": + v, err := strconv.Atoi(value) + if err != nil || v < 0 { + r.cfg.Logger.Log(logger.Warning, pkg+"invalid FilterFrames var", "value", value) + break + } +>>>>>>> d097308e... adding variable to choose how many frames to skip before filtering r.cfg.FilterFrames = v case "PSITime": v, err := strconv.Atoi(value) From 0b95041d4f678d36cca2bfa798007ae4e70b3b2f Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Tue, 7 Jan 2020 16:48:08 +1030 Subject: [PATCH 03/18] quantization = 0 for input encode is MJPEG --- filter/mog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filter/mog.go b/filter/mog.go index cff19d3e..bd916791 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -83,7 +83,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { if hfCount < (m.hf - 1) { m.hold[hfCount] = f hfCount++ - return -1, nil + return 0, nil } else { img, err := gocv.IMDecode(f, gocv.IMReadColor) if err != nil { From 4b285589243ffe208fb9845b10cf50272ac4c4b2 Mon Sep 17 00:00:00 2001 From: Scott Date: Wed, 8 Jan 2020 11:31:09 +1030 Subject: [PATCH 04/18] Frame counter resets on a consistent interval. --- filter/mog.go | 131 +++++++++++++++++++++++++------------------------- 1 file changed, 66 insertions(+), 65 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index bd916791..243044e7 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -84,70 +84,71 @@ func (m *MOGFilter) Write(f []byte) (int, error) { m.hold[hfCount] = f hfCount++ return 0, nil - } else { - img, err := gocv.IMDecode(f, gocv.IMReadColor) - if err != nil { - return 0, fmt.Errorf("image can't be decoded: %w", err) - } - defer img.Close() - - imgDelta := gocv.NewMat() - defer imgDelta.Close() - - // Seperate foreground and background. - m.bs.Apply(img, &imgDelta) - - // Threshold imgDelta. - gocv.Threshold(imgDelta, &imgDelta, 25, 255, gocv.ThresholdBinary) - - // Remove noise. - gocv.Erode(imgDelta, &imgDelta, m.knl) - gocv.Dilate(imgDelta, &imgDelta, m.knl) - - // Fill small holes. - gocv.Dilate(imgDelta, &imgDelta, m.knl) - gocv.Erode(imgDelta, &imgDelta, m.knl) - - // Find contours and reject ones with a small area. - var contours [][]image.Point - allContours := gocv.FindContours(imgDelta, gocv.RetrievalExternal, gocv.ChainApproxSimple) - for _, c := range allContours { - if gocv.ContourArea(c) > m.area { - contours = append(contours, c) - } - } - - // Draw debug information. - if m.debug { - for _, c := range contours { - rect := gocv.BoundingRect(c) - gocv.Rectangle(&img, rect, color.RGBA{0, 0, 255, 0}, 1) - } - - if len(contours) > 0 { - gocv.PutText(&img, "Motion", image.Pt(32, 32), gocv.FontHersheyPlain, 2.0, color.RGBA{255, 0, 0, 0}, 2) - } - - m.windows[0].IMShow(img) - m.windows[1].IMShow(imgDelta) - m.windows[0].WaitKey(1) - } - - // Don't write to destination if there is no motion. - if len(contours) == 0 { - return 0, nil - } - - // Write to destination, past 4 frames then current frame. - for i, h := range m.hold { - _, err := m.dst.Write(h) - m.hold[i] = nil - if err != nil { - return 0, err - } - } - - hfCount = 0 - return m.dst.Write(f) } + + hfCount = 0 + img, err := gocv.IMDecode(f, gocv.IMReadColor) + if err != nil { + return 0, fmt.Errorf("image can't be decoded: %w", err) + } + defer img.Close() + + imgDelta := gocv.NewMat() + defer imgDelta.Close() + + // Seperate foreground and background. + m.bs.Apply(img, &imgDelta) + + // Threshold imgDelta. + gocv.Threshold(imgDelta, &imgDelta, 25, 255, gocv.ThresholdBinary) + + // Remove noise. + gocv.Erode(imgDelta, &imgDelta, m.knl) + gocv.Dilate(imgDelta, &imgDelta, m.knl) + + // Fill small holes. + gocv.Dilate(imgDelta, &imgDelta, m.knl) + gocv.Erode(imgDelta, &imgDelta, m.knl) + + // Find contours and reject ones with a small area. + var contours [][]image.Point + allContours := gocv.FindContours(imgDelta, gocv.RetrievalExternal, gocv.ChainApproxSimple) + for _, c := range allContours { + if gocv.ContourArea(c) > m.area { + contours = append(contours, c) + } + } + + // Draw debug information. + if m.debug { + for _, c := range contours { + rect := gocv.BoundingRect(c) + gocv.Rectangle(&img, rect, color.RGBA{0, 0, 255, 0}, 1) + } + + if len(contours) > 0 { + gocv.PutText(&img, "Motion", image.Pt(32, 32), gocv.FontHersheyPlain, 2.0, color.RGBA{255, 0, 0, 0}, 2) + } + + m.windows[0].IMShow(img) + m.windows[1].IMShow(imgDelta) + m.windows[0].WaitKey(1) + } + + // Don't write to destination if there is no motion. + if len(contours) == 0 { + return 0, nil + } + + // Write to destination, past 4 frames then current frame. + for i, h := range m.hold { + _, err := m.dst.Write(h) + m.hold[i] = nil + if err != nil { + return 0, err + } + } + + return m.dst.Write(f) + } From b0dd41dcf0d2feb9fc49ed30038743807ee106c3 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Thu, 16 Jan 2020 14:39:44 +1030 Subject: [PATCH 05/18] back to no testing --- filter/mog.go | 13 ++++++------- revid/config/config.go | 8 -------- revid/revid.go | 24 ------------------------ 3 files changed, 6 insertions(+), 39 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 243044e7..1b8003a5 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -48,10 +48,9 @@ type MOGFilter struct { windows []*gocv.Window hold [][]byte hf int + hfCount int } -var hfCount int = 0 - // NewMOGFilter returns a pointer to a new MOGFilter struct. func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int) *MOGFilter { bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false) @@ -61,7 +60,7 @@ func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debu windows = []*gocv.Window{gocv.NewWindow("MOG: Bounding boxes"), gocv.NewWindow("MOG: Motion")} } hold := make([][]byte, hf-1) - return &MOGFilter{dst, area, &bs, k, debug, windows, hold, hf} + return &MOGFilter{dst, area, &bs, k, debug, windows, hold, hf, 0} } // Implements io.Closer. @@ -80,13 +79,13 @@ 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) { - if hfCount < (m.hf - 1) { - m.hold[hfCount] = f - hfCount++ + if m.hfCount < (m.hf - 1) { + m.hold[m.hfCount] = f + m.hfCount++ return 0, nil } - hfCount = 0 + m.hfCount = 0 img, err := gocv.IMDecode(f, gocv.IMReadColor) if err != nil { return 0, fmt.Errorf("image can't be decoded: %w", err) diff --git a/revid/config/config.go b/revid/config/config.go index ea1f3b16..b37fc759 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -273,19 +273,11 @@ type Config struct { Width uint // Width defines the input video width Raspivid input. Bitrate uint // Bitrate specifies the bitrate for constant bitrate in kbps. -<<<<<<< HEAD HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input. VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input. Filters []int // Defines the methods of filtering to be used in between lexing and encoding. FilterFrames int // Sets the number of frames that are held before the filter is used (on the nth frame) PSITime int // Sets the time between a packet being sent. -======= - HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input. - VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input. - Filter int // Defines the method of filtering to be used in between lexing and encoding. - FilterFrames int // Sets the number of frames that are held before the filter is used (on the nth frame) - PSITime int // Sets the time between a packet being sent ->>>>>>> d097308e... adding variable to choose how many frames to skip before filtering // Ring buffer parameters. RBMaxElements int // The maximum possible number of elements in ring buffer. diff --git a/revid/revid.go b/revid/revid.go index a375847e..26abdee3 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -344,7 +344,6 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. r.encoders = multiWriter(encoders...) -<<<<<<< HEAD l := len(r.cfg.Filters) r.filters = []filter.Filter{filter.NewNoOp(r.encoders)} if l != 0 { @@ -366,20 +365,7 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. } dst = r.filters[i] } -======= - switch r.cfg.Filter { - case config.FilterNoOp: - r.filter = filter.NewNoOp(r.encoders) - case config.FilterMOG: - r.filter = filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames) - case config.FilterVariableFPS: - r.filter = filter.NewVariableFPSFilter(r.encoders, minFPS, filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames)) - case config.FilterKNN: - r.filter = filter.NewKNNFilter(r.encoders, knnMinArea, knnThreshold, knnHistory, knnKernel, r.cfg.ShowWindows) - default: - panic("Undefined Filter") ->>>>>>> d097308e... adding variable to choose how many frames to skip before filtering } switch r.cfg.Input { @@ -709,16 +695,6 @@ func (r *Revid) Update(vars map[string]string) error { r.cfg.Logger.Log(logger.Warning, pkg+"invalid FilterFrames var", "value", value) break } -<<<<<<< HEAD -======= - r.cfg.Filter = v - case "FilterFrames": - v, err := strconv.Atoi(value) - if err != nil || v < 0 { - r.cfg.Logger.Log(logger.Warning, pkg+"invalid FilterFrames var", "value", value) - break - } ->>>>>>> d097308e... adding variable to choose how many frames to skip before filtering r.cfg.FilterFrames = v case "PSITime": v, err := strconv.Atoi(value) From 61bb0b68f6396c9ca1e0fa84db8472582b50ec45 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Thu, 16 Jan 2020 15:57:57 +1030 Subject: [PATCH 06/18] adding staright to file testing in, need to remove --- revid/revid.go | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/revid/revid.go b/revid/revid.go index 26abdee3..820d10f7 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -32,6 +32,7 @@ import ( "errors" "fmt" "io" + "os" "os/exec" "strconv" "strings" @@ -344,6 +345,15 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. r.encoders = multiWriter(encoders...) + // !!! Test code + //r.encoders = multiWriter(encoders...) + f, er := os.Create("vid.mjpeg") + if er != nil { + panic("!!! TEST CODE !!!: file didnt work") + } + r.encoders = f + // !!! Test code + l := len(r.cfg.Filters) r.filters = []filter.Filter{filter.NewNoOp(r.encoders)} if l != 0 { From 44aac3f9fd115a6934c5a7e9e6c83b3cee027b34 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Mon, 20 Jan 2020 14:09:42 +1030 Subject: [PATCH 07/18] timing for 25 frames testing --- filter/filter.go | 14 +++++++++++++- filter/mog.go | 18 +++++++++++++++++- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/filter/filter.go b/filter/filter.go index ec182531..c6fec897 100644 --- a/filter/filter.go +++ b/filter/filter.go @@ -27,7 +27,9 @@ LICENSE package filter import ( + "fmt" "io" + "time" ) // Interface for all filters. @@ -44,6 +46,16 @@ type NoOp struct { func NewNoOp(dst io.Writer) *NoOp { return &NoOp{dst: dst} } -func (n *NoOp) Write(p []byte) (int, error) { return n.dst.Write(p) } +func (n *NoOp) Write(p []byte) (int, error) { + if frames == 0 { + t1 = time.Now() + } + frames++ + if frames >= 24 { + fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + frames = 0 + } + return n.dst.Write(p) +} func (n *NoOp) Close() error { return nil } diff --git a/filter/mog.go b/filter/mog.go index 1b8003a5..7711c101 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -33,6 +33,7 @@ import ( "image" "image/color" "io" + "time" "gocv.io/x/gocv" ) @@ -51,6 +52,9 @@ type MOGFilter struct { hfCount int } +var frames int = 0 +var t1 = time.Now() + // NewMOGFilter returns a pointer to a new MOGFilter struct. func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int) *MOGFilter { bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false) @@ -79,9 +83,17 @@ 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) { + if frames == 0 { + t1 = time.Now() + } if m.hfCount < (m.hf - 1) { m.hold[m.hfCount] = f m.hfCount++ + frames++ + if frames >= 24 { + fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + frames = 0 + } return 0, nil } @@ -138,7 +150,11 @@ func (m *MOGFilter) Write(f []byte) (int, error) { if len(contours) == 0 { return 0, nil } - + frames++ + if frames >= 24 { + fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + frames = 0 + } // Write to destination, past 4 frames then current frame. for i, h := range m.hold { _, err := m.dst.Write(h) From c99d3564bf980c728de56d55e68c18758f53fd22 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Mon, 20 Jan 2020 14:31:40 +1030 Subject: [PATCH 08/18] more testing --- filter/mog.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 7711c101..d7223c92 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -83,6 +83,7 @@ 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) { + t2 := time.Now() if frames == 0 { t1 = time.Now() } @@ -90,6 +91,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { m.hold[m.hfCount] = f m.hfCount++ frames++ + fmt.Printf("Hold in array 1 frame:\t%dms\n", time.Now().Sub(t2).Milliseconds()) if frames >= 24 { fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) frames = 0 @@ -148,13 +150,15 @@ func (m *MOGFilter) Write(f []byte) (int, error) { // Don't write to destination if there is no motion. if len(contours) == 0 { + frames++ + fmt.Printf("No motion 1 frame:\t%dms\n", time.Now().Sub(t2).Milliseconds()) + if frames >= 24 { + fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + frames = 0 + } return 0, nil } - frames++ - if frames >= 24 { - fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) - frames = 0 - } + // Write to destination, past 4 frames then current frame. for i, h := range m.hold { _, err := m.dst.Write(h) @@ -163,7 +167,12 @@ func (m *MOGFilter) Write(f []byte) (int, error) { return 0, err } } - + fmt.Printf("Motion 1 frame:\t\t%dms\n", time.Now().Sub(t2).Milliseconds()) + frames++ + if frames >= 24 { + fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + frames = 0 + } return m.dst.Write(f) } From 0c081e0b23b1746f1542340019b2d8e8524bae3b Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Mon, 20 Jan 2020 15:45:43 +1030 Subject: [PATCH 09/18] more testing prints now in lex --- codec/mjpeg/lex.go | 5 +++++ filter/mog.go | 6 +++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/codec/mjpeg/lex.go b/codec/mjpeg/lex.go index 46ab4ce8..1ab6db14 100644 --- a/codec/mjpeg/lex.go +++ b/codec/mjpeg/lex.go @@ -38,6 +38,8 @@ import ( ) var noDelay = make(chan time.Time) +var frameGet int = 0 +var frameSend int = 0 func init() { close(noDelay) @@ -62,6 +64,7 @@ func Lex(dst io.Writer, src io.Reader, delay time.Duration) error { if n < 2 { return nil } + frameGet++ if err != nil { if err == io.EOF { return nil @@ -88,6 +91,8 @@ func Lex(dst io.Writer, src io.Reader, delay time.Duration) error { } <-tick _, err = dst.Write(buf) + frameSend++ + fmt.Printf("frames into lex: %v frames getting written: %v\t|\t", frameGet, frameSend) if err != nil { return err } diff --git a/filter/mog.go b/filter/mog.go index d7223c92..e0cd757e 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -93,7 +93,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { frames++ fmt.Printf("Hold in array 1 frame:\t%dms\n", time.Now().Sub(t2).Milliseconds()) if frames >= 24 { - fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + fmt.Printf("\t\t\t\t\t\t\t\t25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) frames = 0 } return 0, nil @@ -153,7 +153,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { frames++ fmt.Printf("No motion 1 frame:\t%dms\n", time.Now().Sub(t2).Milliseconds()) if frames >= 24 { - fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + fmt.Printf("\t\t\t\t\t\t\t\t25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) frames = 0 } return 0, nil @@ -170,7 +170,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { fmt.Printf("Motion 1 frame:\t\t%dms\n", time.Now().Sub(t2).Milliseconds()) frames++ if frames >= 24 { - fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) + fmt.Printf("\t\t\t\t\t\t\t\t25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) frames = 0 } return m.dst.Write(f) From d5e0bf773107500eeba7b1f0cc7cc7734ced85a1 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Mon, 20 Jan 2020 16:19:04 +1030 Subject: [PATCH 10/18] remove all tests --- codec/mjpeg/lex.go | 5 ----- filter/filter.go | 14 +------------- filter/mog.go | 26 -------------------------- revid/revid.go | 10 ---------- 4 files changed, 1 insertion(+), 54 deletions(-) diff --git a/codec/mjpeg/lex.go b/codec/mjpeg/lex.go index 1ab6db14..46ab4ce8 100644 --- a/codec/mjpeg/lex.go +++ b/codec/mjpeg/lex.go @@ -38,8 +38,6 @@ import ( ) var noDelay = make(chan time.Time) -var frameGet int = 0 -var frameSend int = 0 func init() { close(noDelay) @@ -64,7 +62,6 @@ func Lex(dst io.Writer, src io.Reader, delay time.Duration) error { if n < 2 { return nil } - frameGet++ if err != nil { if err == io.EOF { return nil @@ -91,8 +88,6 @@ func Lex(dst io.Writer, src io.Reader, delay time.Duration) error { } <-tick _, err = dst.Write(buf) - frameSend++ - fmt.Printf("frames into lex: %v frames getting written: %v\t|\t", frameGet, frameSend) if err != nil { return err } diff --git a/filter/filter.go b/filter/filter.go index c6fec897..ec182531 100644 --- a/filter/filter.go +++ b/filter/filter.go @@ -27,9 +27,7 @@ LICENSE package filter import ( - "fmt" "io" - "time" ) // Interface for all filters. @@ -46,16 +44,6 @@ type NoOp struct { func NewNoOp(dst io.Writer) *NoOp { return &NoOp{dst: dst} } -func (n *NoOp) Write(p []byte) (int, error) { - if frames == 0 { - t1 = time.Now() - } - frames++ - if frames >= 24 { - fmt.Printf("25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) - frames = 0 - } - return n.dst.Write(p) -} +func (n *NoOp) Write(p []byte) (int, error) { return n.dst.Write(p) } func (n *NoOp) Close() error { return nil } diff --git a/filter/mog.go b/filter/mog.go index e0cd757e..a14b1fe7 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -33,7 +33,6 @@ import ( "image" "image/color" "io" - "time" "gocv.io/x/gocv" ) @@ -52,9 +51,6 @@ type MOGFilter struct { hfCount int } -var frames int = 0 -var t1 = time.Now() - // NewMOGFilter returns a pointer to a new MOGFilter struct. func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int) *MOGFilter { bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false) @@ -83,19 +79,9 @@ 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) { - t2 := time.Now() - if frames == 0 { - t1 = time.Now() - } if m.hfCount < (m.hf - 1) { m.hold[m.hfCount] = f m.hfCount++ - frames++ - fmt.Printf("Hold in array 1 frame:\t%dms\n", time.Now().Sub(t2).Milliseconds()) - if frames >= 24 { - fmt.Printf("\t\t\t\t\t\t\t\t25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) - frames = 0 - } return 0, nil } @@ -150,12 +136,6 @@ func (m *MOGFilter) Write(f []byte) (int, error) { // Don't write to destination if there is no motion. if len(contours) == 0 { - frames++ - fmt.Printf("No motion 1 frame:\t%dms\n", time.Now().Sub(t2).Milliseconds()) - if frames >= 24 { - fmt.Printf("\t\t\t\t\t\t\t\t25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) - frames = 0 - } return 0, nil } @@ -167,12 +147,6 @@ func (m *MOGFilter) Write(f []byte) (int, error) { return 0, err } } - fmt.Printf("Motion 1 frame:\t\t%dms\n", time.Now().Sub(t2).Milliseconds()) - frames++ - if frames >= 24 { - fmt.Printf("\t\t\t\t\t\t\t\t25 frames takes: %dms\n\n", time.Now().Sub(t1).Milliseconds()) - frames = 0 - } return m.dst.Write(f) } diff --git a/revid/revid.go b/revid/revid.go index 820d10f7..26abdee3 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -32,7 +32,6 @@ import ( "errors" "fmt" "io" - "os" "os/exec" "strconv" "strings" @@ -345,15 +344,6 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. r.encoders = multiWriter(encoders...) - // !!! Test code - //r.encoders = multiWriter(encoders...) - f, er := os.Create("vid.mjpeg") - if er != nil { - panic("!!! TEST CODE !!!: file didnt work") - } - r.encoders = f - // !!! Test code - l := len(r.cfg.Filters) r.filters = []filter.Filter{filter.NewNoOp(r.encoders)} if l != 0 { From b588321d0015608b86f013d89c8414b04d368201 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 13:12:22 +1030 Subject: [PATCH 11/18] adding in so builds with circleci build --- filter/filters_circleci.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filter/filters_circleci.go b/filter/filters_circleci.go index f6d46082..bd9a6fee 100644 --- a/filter/filters_circleci.go +++ b/filter/filters_circleci.go @@ -32,7 +32,7 @@ import ( ) // NewMOGFilter returns a pointer to a new NoOp struct for testing purposes only. -func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool) *NoOp { +func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int) *NoOp { return &NoOp{dst: dst} } From b597fb9a1a21d1c9e2c2d4860f447809ff45aed0 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 14:53:03 +1030 Subject: [PATCH 12/18] commenting and refinement --- filter/mog.go | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index a14b1fe7..1d187e96 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -40,15 +40,15 @@ import ( // MOGFilter is a filter that provides basic motion detection. MoG is short for // Mixture of Gaussians method. type MOGFilter struct { - dst io.WriteCloser - area float64 - bs *gocv.BackgroundSubtractorMOG2 - knl gocv.Mat - debug bool - windows []*gocv.Window - hold [][]byte - hf int - hfCount int + dst io.WriteCloser //writer and closer interface + area float64 //minimum area that motion + bs *gocv.BackgroundSubtractorMOG2 //Uses the MOG algorithm to find the difference between the current and background frame + knl gocv.Mat //matrix that is used for calculations + debug bool //if true then debug windows with the bounding boxes and difference will be shown on the screen + windows []*gocv.Window //holds debug windows + hold [][]byte //will hold all frames up to hf (so only every hf frame is motion detected) + hf int //the number of frames to be held + hfCount int //counter for the hold array } // NewMOGFilter returns a pointer to a new MOGFilter struct. @@ -59,8 +59,7 @@ func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debu if debug { windows = []*gocv.Window{gocv.NewWindow("MOG: Bounding boxes"), gocv.NewWindow("MOG: Motion")} } - hold := make([][]byte, hf-1) - return &MOGFilter{dst, area, &bs, k, debug, windows, hold, hf, 0} + return &MOGFilter{dst, area, &bs, k, debug, windows, make([][]byte, hf-1), hf, 0} } // Implements io.Closer. @@ -82,7 +81,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { if m.hfCount < (m.hf - 1) { m.hold[m.hfCount] = f m.hfCount++ - return 0, nil + return len(f), nil } m.hfCount = 0 From 963b74bed0767ea2d04a8296e47bc0aab56dbafb Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 14:57:35 +1030 Subject: [PATCH 13/18] change variable name FilterFrames to MotionFilter --- filter/mog.go | 1 - revid/config/config.go | 10 +++++----- revid/revid.go | 10 +++++----- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 1d187e96..35c3046a 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -147,5 +147,4 @@ func (m *MOGFilter) Write(f []byte) (int, error) { } } return m.dst.Write(f) - } diff --git a/revid/config/config.go b/revid/config/config.go index b37fc759..19367296 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -85,7 +85,7 @@ const ( defaultClipDuration = 0 defaultAudioInputCodec = codecutil.ADPCM defaultPSITime = 2 - defaultFilterFrames = 1 + defaultMotionInterval = 5 // Ring buffer defaults. defaultRBMaxElements = 10000 @@ -276,7 +276,7 @@ type Config struct { HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input. VerticalFlip bool // VerticalFlip flips video vertically for Raspivid input. Filters []int // Defines the methods of filtering to be used in between lexing and encoding. - FilterFrames int // Sets the number of frames that are held before the filter is used (on the nth frame) + MotionInterval int // Sets the number of frames that are held before the filter is used (on the nth frame) PSITime int // Sets the time between a packet being sent. // Ring buffer parameters. @@ -462,9 +462,9 @@ func (c *Config) Validate() error { c.Logger.Log(logger.Info, pkg+"PSITime bad or unset, defaulting", "PSITime", defaultPSITime) c.PSITime = defaultPSITime } - if c.FilterFrames <= 0 { - c.Logger.Log(logger.Info, pkg+"FilterFrames bad or unset, defaulting", "FilterFrames", defaultFilterFrames) - c.FilterFrames = defaultFilterFrames + if c.MotionInterval <= 0 { + c.Logger.Log(logger.Info, pkg+"MotionInterval bad or unset, defaulting", "MotionInterval", defaultMotionInterval) + c.MotionInterval = defaultMotionInterval } if c.MinFPS <= 0 { diff --git a/revid/revid.go b/revid/revid.go index 26abdee3..d717d66f 100644 --- a/revid/revid.go +++ b/revid/revid.go @@ -355,9 +355,9 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io. case config.FilterNoOp: r.filters[i] = filter.NewNoOp(dst) case config.FilterMOG: - r.filters[i] = filter.NewMOGFilter(dst, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames) + r.filters[i] = filter.NewMOGFilter(dst, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.MotionInterval) case config.FilterVariableFPS: - r.filters[i] = filter.NewVariableFPSFilter(dst, minFPS, filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.FilterFrames)) + r.filters[i] = filter.NewVariableFPSFilter(dst, minFPS, filter.NewMOGFilter(r.encoders, mogMinArea, mogThreshold, mogHistory, r.cfg.ShowWindows, r.cfg.MotionInterval)) case config.FilterKNN: r.filters[i] = filter.NewKNNFilter(dst, knnMinArea, knnThreshold, knnHistory, knnKernel, r.cfg.ShowWindows) default: @@ -689,13 +689,13 @@ func (r *Revid) Update(vars map[string]string) error { } r.cfg.Filters[i] = v } - case "FilterFrames": + case "MotionInterval": v, err := strconv.Atoi(value) if err != nil || v < 0 { - r.cfg.Logger.Log(logger.Warning, pkg+"invalid FilterFrames var", "value", value) + r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionInterval var", "value", value) break } - r.cfg.FilterFrames = v + r.cfg.MotionInterval = v case "PSITime": v, err := strconv.Atoi(value) if err != nil || v < 0 { From fd8e2e2426d972cf731e1c5c16abec2d50c34d73 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 15:25:34 +1030 Subject: [PATCH 14/18] full stops --- filter/mog.go | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 35c3046a..b83b039c 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -40,15 +40,15 @@ import ( // MOGFilter is a filter that provides basic motion detection. MoG is short for // Mixture of Gaussians method. type MOGFilter struct { - dst io.WriteCloser //writer and closer interface - area float64 //minimum area that motion - bs *gocv.BackgroundSubtractorMOG2 //Uses the MOG algorithm to find the difference between the current and background frame - knl gocv.Mat //matrix that is used for calculations - debug bool //if true then debug windows with the bounding boxes and difference will be shown on the screen - windows []*gocv.Window //holds debug windows - hold [][]byte //will hold all frames up to hf (so only every hf frame is motion detected) - hf int //the number of frames to be held - hfCount int //counter for the hold array + dst io.WriteCloser //writer and closer interface. + area float64 //minimum area that motion. + bs *gocv.BackgroundSubtractorMOG2 //Uses the MOG algorithm to find the difference between the current and background frame. + knl gocv.Mat //matrix that is used for calculations. + debug bool //if true then debug windows with the bounding boxes and difference will be shown on the screen. + windows []*gocv.Window //holds debug windows. + hold [][]byte //will hold all frames up to hf (so only every hf frame is motion detected). + hf int //the number of frames to be held. + hfCount int //counter for the hold array. } // NewMOGFilter returns a pointer to a new MOGFilter struct. From 2e70e3fa1bf3eaaab7609f09ec69c6cca3b6e104 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 15:34:32 +1030 Subject: [PATCH 15/18] change to error handling --- filter/mog.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index b83b039c..9519b656 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -87,7 +87,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { m.hfCount = 0 img, err := gocv.IMDecode(f, gocv.IMReadColor) if err != nil { - return 0, fmt.Errorf("image can't be decoded: %w", err) + return len(f), fmt.Errorf("image can't be decoded: %w", err) } defer img.Close() @@ -135,7 +135,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { // Don't write to destination if there is no motion. if len(contours) == 0 { - return 0, nil + return len(f), nil } // Write to destination, past 4 frames then current frame. @@ -143,7 +143,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { _, err := m.dst.Write(h) m.hold[i] = nil if err != nil { - return 0, err + return len(f), fmt.Errorf("could not write previous frames: %w", err) } } return m.dst.Write(f) From c3f1d957e3ef147bae08d5857be73ca6305fe2b4 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 15:43:10 +1030 Subject: [PATCH 16/18] formatting --- filter/mog.go | 18 +++++++++--------- revid/config/config.go | 1 + 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index 9519b656..b86e1cdf 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -40,15 +40,15 @@ import ( // MOGFilter is a filter that provides basic motion detection. MoG is short for // Mixture of Gaussians method. type MOGFilter struct { - dst io.WriteCloser //writer and closer interface. - area float64 //minimum area that motion. - bs *gocv.BackgroundSubtractorMOG2 //Uses the MOG algorithm to find the difference between the current and background frame. - knl gocv.Mat //matrix that is used for calculations. - debug bool //if true then debug windows with the bounding boxes and difference will be shown on the screen. - windows []*gocv.Window //holds debug windows. - hold [][]byte //will hold all frames up to hf (so only every hf frame is motion detected). - hf int //the number of frames to be held. - hfCount int //counter for the hold array. + dst io.WriteCloser // Writer and closer interface. + area float64 // Minimum area that motion. + bs *gocv.BackgroundSubtractorMOG2 // Uses the MOG algorithm to find the difference between the current and background frame. + knl gocv.Mat // Matrix that is used for calculations. + debug bool // If true then debug windows with the bounding boxes and difference will be shown on the screen. + windows []*gocv.Window // Holds debug windows. + hold [][]byte // Will hold all frames up to hf (so only every hf frame is motion detected). + hf int // The number of frames to be held. + hfCount int // Counter for the hold array. } // NewMOGFilter returns a pointer to a new MOGFilter struct. diff --git a/revid/config/config.go b/revid/config/config.go index 19367296..5f6fa4b3 100644 --- a/revid/config/config.go +++ b/revid/config/config.go @@ -328,6 +328,7 @@ var TypeData = map[string]string{ "MOGHistory": "uint", "MOGMinArea": "float", "MOGThreshold": "float", + "MotionInterval": "int", "RBCapacity": "uint", "RBMaxElements": "uint", "RBWriteTimeout": "uint", From c9dee735d43b6295d8ab711595d5efacd1dd872e Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 15:44:53 +1030 Subject: [PATCH 17/18] back to old return --- filter/mog.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/filter/mog.go b/filter/mog.go index b86e1cdf..ca318140 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -87,7 +87,7 @@ func (m *MOGFilter) Write(f []byte) (int, error) { m.hfCount = 0 img, err := gocv.IMDecode(f, gocv.IMReadColor) if err != nil { - return len(f), fmt.Errorf("image can't be decoded: %w", err) + return 0, fmt.Errorf("image can't be decoded: %w", err) } defer img.Close() From 3851a20aa05c94536895ff3b88c5a35af0a9a520 Mon Sep 17 00:00:00 2001 From: Ella Pietraroia Date: Wed, 22 Jan 2020 16:04:16 +1030 Subject: [PATCH 18/18] commenting --- filter/mog.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/filter/mog.go b/filter/mog.go index ca318140..20fd5807 100644 --- a/filter/mog.go +++ b/filter/mog.go @@ -40,8 +40,8 @@ import ( // MOGFilter is a filter that provides basic motion detection. MoG is short for // Mixture of Gaussians method. type MOGFilter struct { - dst io.WriteCloser // Writer and closer interface. - area float64 // Minimum area that motion. + dst io.WriteCloser // Destination to which motion containing frames go. + area float64 // The minimum area that a contour can be found in. bs *gocv.BackgroundSubtractorMOG2 // Uses the MOG algorithm to find the difference between the current and background frame. knl gocv.Mat // Matrix that is used for calculations. debug bool // If true then debug windows with the bounding boxes and difference will be shown on the screen.