mirror of https://bitbucket.org/ausocean/av.git
Merged in less-frames-knn (pull request #346)
Less frames knn Approved-by: Saxon Milton <saxon.milton@gmail.com>
This commit is contained in:
commit
8ac664f11e
|
@ -36,6 +36,6 @@ func NewMOGFilter(dst io.WriteCloser, area, threshold float64, history int, debu
|
||||||
return &NoOp{dst: dst}
|
return &NoOp{dst: dst}
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewKNNFilter(dst io.WriteCloser, area, threshold float64, history, kernelSize int, debug bool) *NoOp {
|
func NewKNNFilter(dst io.WriteCloser, area, threshold float64, history, kernelSize int, debug bool, hf int) *NoOp {
|
||||||
return &NoOp{dst: dst}
|
return &NoOp{dst: dst}
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,23 +40,26 @@ import (
|
||||||
// KNNFilter is a filter that provides basic motion detection. KNN is short for
|
// KNNFilter is a filter that provides basic motion detection. KNN is short for
|
||||||
// K-Nearest Neighbours method.
|
// K-Nearest Neighbours method.
|
||||||
type KNNFilter struct {
|
type KNNFilter struct {
|
||||||
dst io.WriteCloser
|
dst io.WriteCloser // Destination to which motion containing frames go.
|
||||||
area float64
|
area float64 // The minimum area that a contour can be found in.
|
||||||
bs *gocv.BackgroundSubtractorKNN
|
bs *gocv.BackgroundSubtractorKNN // Uses the KNN algorithm to find the difference between the current and background frame.
|
||||||
knl gocv.Mat
|
knl gocv.Mat // Matrix that is used for calculations.
|
||||||
debug bool
|
debug bool // If true then debug windows with the bounding boxes and difference will be shown on the screen.
|
||||||
windows []*gocv.Window
|
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.
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewKNNFilter returns a pointer to a new KNNFilter.
|
// NewKNNFilter returns a pointer to a new KNNFilter.
|
||||||
func NewKNNFilter(dst io.WriteCloser, area, threshold float64, history, kernelSize int, debug bool) *KNNFilter {
|
func NewKNNFilter(dst io.WriteCloser, area, threshold float64, history, kernelSize int, debug bool, hf int) *KNNFilter {
|
||||||
bs := gocv.NewBackgroundSubtractorKNNWithParams(history, threshold, false)
|
bs := gocv.NewBackgroundSubtractorKNNWithParams(history, threshold, false)
|
||||||
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(kernelSize, kernelSize))
|
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(kernelSize, kernelSize))
|
||||||
var windows []*gocv.Window
|
var windows []*gocv.Window
|
||||||
if debug {
|
if debug {
|
||||||
windows = []*gocv.Window{gocv.NewWindow("KNN: Bounding boxes"), gocv.NewWindow("KNN: Motion")}
|
windows = []*gocv.Window{gocv.NewWindow("KNN: Bounding boxes"), gocv.NewWindow("KNN: Motion")}
|
||||||
}
|
}
|
||||||
return &KNNFilter{dst, area, &bs, k, debug, windows}
|
return &KNNFilter{dst, area, &bs, k, debug, windows, make([][]byte, hf-1), hf, 0}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements io.Closer.
|
// Implements io.Closer.
|
||||||
|
@ -75,6 +78,13 @@ func (m *KNNFilter) 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 *KNNFilter) Write(f []byte) (int, error) {
|
func (m *KNNFilter) Write(f []byte) (int, error) {
|
||||||
|
if m.hfCount < (m.hf - 1) {
|
||||||
|
m.hold[m.hfCount] = f
|
||||||
|
m.hfCount++
|
||||||
|
return len(f), nil
|
||||||
|
}
|
||||||
|
m.hfCount = 0
|
||||||
|
|
||||||
img, err := gocv.IMDecode(f, gocv.IMReadColor)
|
img, err := gocv.IMDecode(f, gocv.IMReadColor)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 0, fmt.Errorf("can't decode image: %w", err)
|
return 0, fmt.Errorf("can't decode image: %w", err)
|
||||||
|
@ -125,9 +135,16 @@ func (m *KNNFilter) 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 -1, nil
|
return len(f), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write to destination.
|
// 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 len(f), fmt.Errorf("could not write previous frames: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
return m.dst.Write(f)
|
return m.dst.Write(f)
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,7 +341,7 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
|
||||||
case config.FilterVariableFPS:
|
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.cfg.MotionInterval))
|
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.cfg.MotionInterval))
|
||||||
case config.FilterKNN:
|
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, r.cfg.KNNMinArea, r.cfg.KNNThreshold, int(r.cfg.KNNHistory), int(r.cfg.KNNKernel), r.cfg.ShowWindows, r.cfg.MotionInterval)
|
||||||
default:
|
default:
|
||||||
panic("Undefined Filter")
|
panic("Undefined Filter")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue