filter: combine common filter variables

This commit is contained in:
Scott 2020-02-06 09:42:12 +10:30
parent bb5618f3c7
commit 5f02bb3829
7 changed files with 185 additions and 207 deletions

View File

@ -34,6 +34,13 @@ import (
"image/jpeg" "image/jpeg"
"io" "io"
"sync" "sync"
"bitbucket.org/ausocean/av/revid/config"
)
const (
defaultBasicThreshold = 45000
defaultBasicPixels = 1000
) )
type pixel struct{ r, g, b uint32 } type pixel struct{ r, g, b uint32 }
@ -54,11 +61,22 @@ type Basic struct {
} }
// NewBasic returns a pointer to a new Basic filter struct. // NewBasic returns a pointer to a new Basic filter struct.
func NewBasic(dst io.WriteCloser, t, p int) *Basic { func NewBasic(dst io.WriteCloser, c config.Config) *Basic {
// Validate parameters.
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultBasicThreshold)
c.MotionThreshold = defaultBasicThreshold
}
if c.MotionPixels <= 0 {
c.LogInvalidField("MotionPixels", defaultBasicPixels)
c.MotionPixels = defaultBasicPixels
}
return &Basic{ return &Basic{
dst: dst, dst: dst,
thresh: t, thresh: int(c.MotionThreshold),
pix: p, pix: c.MotionPixels,
debugging: newWindows("BASIC"), debugging: newWindows("BASIC"),
} }
} }

View File

@ -33,9 +33,12 @@ import (
"fmt" "fmt"
"io" "io"
"bitbucket.org/ausocean/av/revid/config"
"gocv.io/x/gocv" "gocv.io/x/gocv"
) )
const defaultDiffThreshold = 3
// Difference is a filter that provides basic motion detection. Difference calculates // Difference is a filter that provides basic motion detection. Difference calculates
// the absolute difference for each pixel between two frames, then finds the mean. If // the absolute difference for each pixel between two frames, then finds the mean. If
// the mean is above a given threshold, then it is considered motion. // the mean is above a given threshold, then it is considered motion.
@ -47,10 +50,16 @@ type Difference struct {
} }
// NewDifference returns a pointer to a new Difference struct. // NewDifference returns a pointer to a new Difference struct.
func NewDifference(dst io.WriteCloser, threshold float64) *Difference { func NewDifference(dst io.WriteCloser, c config.Config) *Difference {
// Validate parameters.
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultDiffThreshold)
c.MotionThreshold = defaultDiffThreshold
}
return &Difference{ return &Difference{
dst: dst, dst: dst,
thresh: threshold, thresh: c.MotionThreshold,
prev: gocv.NewMat(), prev: gocv.NewMat(),
debugging: newWindows("DIFF"), debugging: newWindows("DIFF"),
} }

View File

@ -30,20 +30,22 @@ package filter
import ( import (
"image" "image"
"io" "io"
"bitbucket.org/ausocean/av/revid/config"
) )
// NewMOG returns a pointer to a new NoOp struct for testing purposes only. // NewMOG returns a pointer to a new NoOp struct for testing purposes only.
func NewMOG(dst io.WriteCloser, area, threshold float64, history int, hf int, scaleFactor int) *NoOp { func NewMOG(dst io.WriteCloser, c config.Config) *NoOp {
return &NoOp{dst: dst} return &NoOp{dst: dst}
} }
// NewKNN returns a pointer to a new NoOp struct for testing purposes only. // NewKNN returns a pointer to a new NoOp struct for testing purposes only.
func NewKNN(dst io.WriteCloser, area, threshold float64, history, kernelSize int, hf int, scaleFactor int) *NoOp { func NewKNN(dst io.WriteCloser, c config.Config) *NoOp {
return &NoOp{dst: dst} return &NoOp{dst: dst}
} }
// NewDiffference returns a pointer to a new NoOp struct for testing purposes only. // NewDiffference returns a pointer to a new NoOp struct for testing purposes only.
func NewDifference(dst io.WriteCloser, threshold float64) *NoOp { func NewDifference(dst io.WriteCloser, c config.Config) *NoOp {
return &NoOp{dst: dst} return &NoOp{dst: dst}
} }

View File

@ -33,9 +33,19 @@ import (
"image" "image"
"io" "io"
"bitbucket.org/ausocean/av/revid/config"
"gocv.io/x/gocv" "gocv.io/x/gocv"
) )
const (
defaultKNNMinArea = 25.0
defaultKNNThreshold = 300
defaultKNNHistory = 300
defaultKNNKernel = 4
defaultKNNDownscaling = 2
defaultKNNInterval = 1
)
// KNN is a filter that provides basic motion detection. KNN is short for // KNN is a filter that provides basic motion detection. KNN is short for
// K-Nearest Neighbours method. // K-Nearest Neighbours method.
type KNN struct { type KNN struct {
@ -51,17 +61,44 @@ type KNN struct {
} }
// NewKNN returns a pointer to a new KNN filter struct. // NewKNN returns a pointer to a new KNN filter struct.
func NewKNN(dst io.WriteCloser, area, threshold float64, history, kernelSize int, hf int, scaleFactor int) *KNN { func NewKNN(dst io.WriteCloser, c config.Config) *KNN {
bs := gocv.NewBackgroundSubtractorKNNWithParams(history, threshold, false) // Validate parameters.
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(kernelSize, kernelSize)) if c.MotionMinArea <= 0 {
c.LogInvalidField("MotionMinArea", defaultKNNMinArea)
c.MotionMinArea = defaultKNNMinArea
}
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultKNNThreshold)
c.MotionThreshold = defaultKNNThreshold
}
if c.MotionHistory == 0 {
c.LogInvalidField("MotionHistory", defaultKNNHistory)
c.MotionHistory = defaultKNNHistory
}
if c.MotionDownscaling <= 0 {
c.LogInvalidField("MotionDownscaling", defaultKNNDownscaling)
c.MotionDownscaling = defaultKNNDownscaling
}
if c.MotionInterval <= 0 {
c.LogInvalidField("MotionInterval", defaultKNNInterval)
c.MotionInterval = defaultKNNInterval
}
if c.MotionKernel <= 0 {
c.LogInvalidField("MotionKernel", defaultKNNKernel)
c.MotionKernel = defaultKNNKernel
}
bs := gocv.NewBackgroundSubtractorKNNWithParams(int(c.MotionHistory), c.MotionThreshold, false)
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(int(c.MotionKernel), int(c.MotionKernel)))
return &KNN{ return &KNN{
dst: dst, dst: dst,
area: area, area: c.MotionMinArea,
bs: &bs, bs: &bs,
knl: k, knl: k,
hold: make([][]byte, hf-1), hold: make([][]byte, c.MotionInterval-1),
hf: hf, hf: c.MotionInterval,
scale: 1 / float64(scaleFactor), scale: 1 / float64(c.MotionDownscaling),
debugging: newWindows("KNN"), debugging: newWindows("KNN"),
} }
} }

View File

@ -33,9 +33,19 @@ import (
"image" "image"
"io" "io"
"bitbucket.org/ausocean/av/revid/config"
"gocv.io/x/gocv" "gocv.io/x/gocv"
) )
const (
defaultMOGMinArea = 25.0
defaultMOGThreshold = 20.0
defaultMOGHistory = 500
defaultMOGKernel = 3
defaultMOGDownscaling = 2
defaultMOGInterval = 1
)
// MOG is a filter that provides basic motion detection. MoG is short for // MOG is a filter that provides basic motion detection. MoG is short for
// Mixture of Gaussians method. // Mixture of Gaussians method.
type MOG struct { type MOG struct {
@ -51,17 +61,43 @@ type MOG struct {
} }
// NewMOG returns a pointer to a new MOG filter struct. // NewMOG returns a pointer to a new MOG filter struct.
func NewMOG(dst io.WriteCloser, area, threshold float64, history int, hf int, scaleFactor int) *MOG { func NewMOG(dst io.WriteCloser, c config.Config) *MOG {
bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false) // Validate parameters.
if c.MotionMinArea <= 0 {
c.LogInvalidField("MotionMinArea", defaultMOGMinArea)
c.MotionMinArea = defaultMOGMinArea
}
if c.MotionThreshold <= 0 {
c.LogInvalidField("MotionThreshold", defaultMOGThreshold)
c.MotionThreshold = defaultMOGThreshold
}
if c.MotionHistory == 0 {
c.LogInvalidField("MotionHistory", defaultMOGHistory)
c.MotionHistory = defaultMOGHistory
}
if c.MotionDownscaling <= 0 {
c.LogInvalidField("MotionDownscaling", defaultMOGDownscaling)
c.MotionDownscaling = defaultMOGDownscaling
}
if c.MotionInterval <= 0 {
c.LogInvalidField("MotionInterval", defaultMOGInterval)
c.MotionInterval = defaultMOGInterval
}
if c.MotionKernel <= 0 {
c.LogInvalidField("MotionKernel", defaultMOGKernel)
c.MotionKernel = defaultMOGKernel
}
bs := gocv.NewBackgroundSubtractorMOG2WithParams(int(c.MotionHistory), c.MotionThreshold, false)
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3)) k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3))
return &MOG{ return &MOG{
dst: dst, dst: dst,
area: area, area: c.MotionMinArea,
bs: &bs, bs: &bs,
knl: k, knl: k,
hold: make([][]byte, hf-1), hold: make([][]byte, c.MotionInterval-1),
hf: hf, hf: c.MotionInterval,
scale: 1 / float64(scaleFactor), scale: 1 / float64(c.MotionDownscaling),
debugging: newWindows("MOG"), debugging: newWindows("MOG"),
} }
} }

View File

@ -91,24 +91,7 @@ const (
defaultRBWriteTimeout = 5 defaultRBWriteTimeout = 5
// Motion filter parameter defaults. // Motion filter parameter defaults.
defaultMinFPS = 1.0 defaultMinFPS = 1.0
defaultMotionDownscaling = 1
defaultMotionInterval = 1
// KNN filter parameter defaults.
defaultKNNMinArea = 25.0
defaultKNNThreshold = 300
defaultKNNHistory = 300
defaultKNNKernel = 9
// MOG filter parameter defaults.
defaultMOGMinArea = 25.0
defaultMOGThreshold = 20.0
defaultMOGHistory = 500
// Basic filter parameter defaults
defaultBasicThreshold = 45000
defaultBasicPixels = 1000
) )
// Quality represents video quality. // Quality represents video quality.
@ -283,27 +266,16 @@ type Config struct {
RBWriteTimeout int // The ringbuffer write timeout in seconds. RBWriteTimeout int // The ringbuffer write timeout in seconds.
// Motion filter parameters. // Motion filter parameters.
// Some parameters can be used with any filter, while others can only be used by a few.
MinFPS float64 // The reduced framerate of the video when there is no motion. MinFPS float64 // The reduced framerate of the video when there is no motion.
MotionInterval 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).
MotionDownscaling int // Downscaling factor of frames used for motion detection. MotionDownscaling int // Downscaling factor of frames used for motion detection.
// KNN filter parameters. MotionMinArea float64 // Used to ignore small areas of motion detection (KNN & MOG only).
KNNMinArea float64 // Used to ignore small areas of motion detection. MotionThreshold float64 // Intensity value that is considered motion.
KNNThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion. MotionHistory uint // Length of filter's history (KNN & MOG only).
KNNHistory uint // Length of KNN filter's history MotionKernel uint // Size of kernel used for filling holes and removing noise (KNN only).
KNNKernel uint // Size of kernel used for filling holes and removing noise. MotionPixels int // Number of pixels with motion that is needed for a whole frame to be considered as moving (Basic only).
// MOG filter parameters.
MOGMinArea float64 // Used to ignore small areas of motion detection.
MOGThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
MOGHistory uint // Length of MOG filter's history.
// Difference filter parameters.
DiffThreshold float64 // Intensity value from the Difference motion detection algorithm that is considered motion.
// Basic filter parameters.
BasicThreshold int
BasicPixels int
// If true will restart reading of input after an io.EOF. // If true will restart reading of input after an io.EOF.
Loop bool Loop bool
@ -316,8 +288,6 @@ type Config struct {
// can be set over the web. It is a psuedo const. // can be set over the web. It is a psuedo const.
var TypeData = map[string]string{ var TypeData = map[string]string{
"AutoWhiteBalance": "enum:off,auto,sun,cloud,shade,tungsten,fluorescent,incandescent,flash,horizon", "AutoWhiteBalance": "enum:off,auto,sun,cloud,shade,tungsten,fluorescent,incandescent,flash,horizon",
"BasicPixels": "int",
"BasicThreshold": "int",
"BitDepth": "int", "BitDepth": "int",
"Brightness": "uint", "Brightness": "uint",
"BurstPeriod": "uint", "BurstPeriod": "uint",
@ -325,7 +295,6 @@ var TypeData = map[string]string{
"CameraIP": "string", "CameraIP": "string",
"CBR": "bool", "CBR": "bool",
"ClipDuration": "uint", "ClipDuration": "uint",
"DiffThreshold": "float",
"Exposure": "enum:auto,night,nightpreview,backlight,spotlight,sports,snow,beach,verylong,fixedfps,antishake,fireworks", "Exposure": "enum:auto,night,nightpreview,backlight,spotlight,sports,snow,beach,verylong,fixedfps,antishake,fireworks",
"FileFPS": "int", "FileFPS": "int",
"Filters": "enums:NoOp,MOG,VariableFPS,KNN,Difference,Basic", "Filters": "enums:NoOp,MOG,VariableFPS,KNN,Difference,Basic",
@ -336,20 +305,18 @@ var TypeData = map[string]string{
"Input": "enum:raspivid,rtsp,v4l,file", "Input": "enum:raspivid,rtsp,v4l,file",
"InputCodec": "enum:H264,MJPEG", "InputCodec": "enum:H264,MJPEG",
"InputPath": "string", "InputPath": "string",
"KNNHistory": "uint",
"KNNKernel": "float",
"KNNMinArea": "float",
"KNNThreshold": "float",
"logging": "enum:Debug,Info,Warning,Error,Fatal", "logging": "enum:Debug,Info,Warning,Error,Fatal",
"Loop": "bool", "Loop": "bool",
"MinFPS": "float", "MinFPS": "float",
"MinFrames": "uint", "MinFrames": "uint",
"mode": "enum:Normal,Paused,Burst,Loop", "mode": "enum:Normal,Paused,Burst,Loop",
"MOGHistory": "uint",
"MOGMinArea": "float",
"MOGThreshold": "float",
"MotionDownscaling": "uint", "MotionDownscaling": "uint",
"MotionHistory": "uint",
"MotionInterval": "int", "MotionInterval": "int",
"MotionKernel": "uint",
"MotionMinArea": "float",
"MotionPixels": "int",
"MotionThreshold": "float",
"Output": "enum:File,Http,Rtmp,Rtp", "Output": "enum:File,Http,Rtmp,Rtp",
"OutputPath": "string", "OutputPath": "string",
"Outputs": "enums:File,Http,Rtmp,Rtp", "Outputs": "enums:File,Http,Rtmp,Rtp",
@ -378,19 +345,19 @@ func (c *Config) Validate() error {
switch c.LogLevel { switch c.LogLevel {
case logger.Debug, logger.Info, logger.Warning, logger.Error, logger.Fatal: case logger.Debug, logger.Info, logger.Warning, logger.Error, logger.Fatal:
default: default:
c.logInvalidField("LogLevel", defaultVerbosity) c.LogInvalidField("LogLevel", defaultVerbosity)
c.LogLevel = defaultVerbosity c.LogLevel = defaultVerbosity
} }
if c.CameraIP == "" { if c.CameraIP == "" {
c.logInvalidField("CameraIP", defaultCameraIP) c.LogInvalidField("CameraIP", defaultCameraIP)
c.CameraIP = defaultCameraIP c.CameraIP = defaultCameraIP
} }
switch c.Input { switch c.Input {
case InputRaspivid, InputV4L, InputFile, InputAudio, InputRTSP: case InputRaspivid, InputV4L, InputFile, InputAudio, InputRTSP:
case NothingDefined: case NothingDefined:
c.logInvalidField("Input", defaultInput) c.LogInvalidField("Input", defaultInput)
c.Input = defaultInput c.Input = defaultInput
default: default:
return errors.New("bad input type defined in config") return errors.New("bad input type defined in config")
@ -401,16 +368,16 @@ func (c *Config) Validate() error {
default: default:
switch c.Input { switch c.Input {
case OutputAudio: case OutputAudio:
c.logInvalidField("InputCodec", defaultAudioInputCodec) c.LogInvalidField("InputCodec", defaultAudioInputCodec)
c.InputCodec = defaultAudioInputCodec c.InputCodec = defaultAudioInputCodec
default: default:
c.logInvalidField("InputCodec", defaultInputCodec) c.LogInvalidField("InputCodec", defaultInputCodec)
c.InputCodec = defaultInputCodec c.InputCodec = defaultInputCodec
} }
} }
if c.Outputs == nil { if c.Outputs == nil {
c.logInvalidField("Outputs", defaultOutput) c.LogInvalidField("Outputs", defaultOutput)
c.Outputs = append(c.Outputs, defaultOutput) c.Outputs = append(c.Outputs, defaultOutput)
} }
@ -428,14 +395,14 @@ func (c *Config) Validate() error {
} }
if c.BurstPeriod == 0 { if c.BurstPeriod == 0 {
c.logInvalidField("BurstPeriod", defaultBurstPeriod) c.LogInvalidField("BurstPeriod", defaultBurstPeriod)
c.BurstPeriod = defaultBurstPeriod c.BurstPeriod = defaultBurstPeriod
} }
const maxMinFrames = 1000 const maxMinFrames = 1000
switch { switch {
case c.MinFrames == 0: case c.MinFrames == 0:
c.logInvalidField("MinFrames", defaultMinFrames) c.LogInvalidField("MinFrames", defaultMinFrames)
c.MinFrames = defaultMinFrames c.MinFrames = defaultMinFrames
case c.MinFrames < 0: case c.MinFrames < 0:
return errors.New("refresh period is less than 0") return errors.New("refresh period is less than 0")
@ -444,115 +411,60 @@ func (c *Config) Validate() error {
} }
if c.FrameRate <= 0 { if c.FrameRate <= 0 {
c.logInvalidField("FrameRate", defaultFrameRate) c.LogInvalidField("FrameRate", defaultFrameRate)
c.FrameRate = defaultFrameRate c.FrameRate = defaultFrameRate
} }
if c.WriteRate <= 0 { if c.WriteRate <= 0 {
c.logInvalidField("writeRate", defaultWriteRate) c.LogInvalidField("writeRate", defaultWriteRate)
c.WriteRate = defaultWriteRate c.WriteRate = defaultWriteRate
} }
if c.ClipDuration == 0 { if c.ClipDuration == 0 {
c.logInvalidField("ClipDuration", defaultClipDuration) c.LogInvalidField("ClipDuration", defaultClipDuration)
c.ClipDuration = defaultClipDuration c.ClipDuration = defaultClipDuration
} else if c.ClipDuration < 0 { } else if c.ClipDuration < 0 {
return errors.New("clip duration is less than 0") return errors.New("clip duration is less than 0")
} }
if c.RTPAddress == "" { if c.RTPAddress == "" {
c.logInvalidField("RTPAddress", defaultRtpAddr) c.LogInvalidField("RTPAddress", defaultRtpAddr)
c.RTPAddress = defaultRtpAddr c.RTPAddress = defaultRtpAddr
} }
if c.RBMaxElements <= 0 { if c.RBMaxElements <= 0 {
c.logInvalidField("RBMaxElements", defaultRBMaxElements) c.LogInvalidField("RBMaxElements", defaultRBMaxElements)
c.RBMaxElements = defaultRBMaxElements c.RBMaxElements = defaultRBMaxElements
} }
if c.RBCapacity <= 0 { if c.RBCapacity <= 0 {
c.logInvalidField("RBCapacity", defaultRBCapacity) c.LogInvalidField("RBCapacity", defaultRBCapacity)
c.RBCapacity = defaultRBCapacity c.RBCapacity = defaultRBCapacity
} }
if c.RBWriteTimeout <= 0 { if c.RBWriteTimeout <= 0 {
c.logInvalidField("RBWriteTimeout", defaultRBWriteTimeout) c.LogInvalidField("RBWriteTimeout", defaultRBWriteTimeout)
c.RBWriteTimeout = defaultRBWriteTimeout c.RBWriteTimeout = defaultRBWriteTimeout
} }
if c.PSITime <= 0 { if c.PSITime <= 0 {
c.logInvalidField("PSITime", defaultPSITime) c.LogInvalidField("PSITime", defaultPSITime)
c.PSITime = defaultPSITime c.PSITime = defaultPSITime
} }
if c.MotionInterval <= 0 {
c.logInvalidField("MotionInterval", defaultMotionInterval)
c.MotionInterval = defaultMotionInterval
}
if c.MinFPS <= 0 { if c.MinFPS <= 0 {
c.logInvalidField("MinFPS", defaultMinFPS) c.LogInvalidField("MinFPS", defaultMinFPS)
c.MinFPS = defaultMinFPS c.MinFPS = defaultMinFPS
} }
if c.KNNMinArea <= 0 {
c.logInvalidField("KNNMinArea", defaultKNNMinArea)
c.KNNMinArea = defaultKNNMinArea
}
if c.KNNThreshold <= 0 {
c.logInvalidField("KNNThreshold", defaultKNNThreshold)
c.KNNThreshold = defaultKNNThreshold
}
if c.KNNHistory == 0 {
c.logInvalidField("KNNHistory", defaultKNNHistory)
c.KNNHistory = defaultKNNHistory
}
if c.KNNKernel <= 0 {
c.logInvalidField("KNNKernel", defaultKNNKernel)
c.KNNKernel = defaultKNNKernel
}
if c.MOGMinArea <= 0 {
c.logInvalidField("MOGMinArea", defaultMOGMinArea)
c.MOGMinArea = defaultMOGMinArea
}
if c.MOGThreshold <= 0 {
c.logInvalidField("MOGThreshold", defaultMOGThreshold)
c.MOGThreshold = defaultMOGThreshold
}
if c.MOGHistory == 0 {
c.logInvalidField("MOGHistory", defaultMOGHistory)
c.MOGHistory = defaultMOGHistory
}
if c.BasicThreshold <= 0 {
c.logInvalidField("BasicThreshold", defaultBasicThreshold)
c.BasicThreshold = defaultBasicThreshold
}
if c.BasicPixels <= 0 {
c.logInvalidField("BasicPixels", defaultBasicPixels)
c.BasicPixels = defaultBasicPixels
}
if c.MotionDownscaling <= 0 {
c.logInvalidField("MotionDownscaling", defaultMotionDownscaling)
c.MotionDownscaling = defaultMotionDownscaling
}
if c.FileFPS <= 0 || (c.FileFPS > 0 && c.Input != InputFile) { if c.FileFPS <= 0 || (c.FileFPS > 0 && c.Input != InputFile) {
c.logInvalidField("FileFPS", defaultFileFPS) c.LogInvalidField("FileFPS", defaultFileFPS)
c.FileFPS = defaultFileFPS c.FileFPS = defaultFileFPS
} }
return nil return nil
} }
func (c *Config) logInvalidField(name string, def interface{}) { func (c *Config) LogInvalidField(name string, def interface{}) {
c.Logger.Log(logger.Info, pkg+name+" bad or unset, defaulting", name, def) c.Logger.Log(logger.Info, pkg+name+" bad or unset, defaulting", name, def)
} }

View File

@ -334,15 +334,15 @@ func (r *Revid) setupPipeline(mtsEnc func(dst io.WriteCloser, rate float64) (io.
case config.FilterNoOp: case config.FilterNoOp:
r.filters[i] = filter.NewNoOp(dst) r.filters[i] = filter.NewNoOp(dst)
case config.FilterMOG: case config.FilterMOG:
r.filters[i] = filter.NewMOG(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.MotionInterval, r.cfg.MotionDownscaling) r.filters[i] = filter.NewMOG(dst, r.cfg)
case config.FilterVariableFPS: case config.FilterVariableFPS:
r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.MotionInterval, r.cfg.MotionDownscaling)) r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg))
case config.FilterKNN: case config.FilterKNN:
r.filters[i] = filter.NewKNN(dst, r.cfg.KNNMinArea, r.cfg.KNNThreshold, int(r.cfg.KNNHistory), int(r.cfg.KNNKernel), r.cfg.MotionInterval, r.cfg.MotionDownscaling) r.filters[i] = filter.NewKNN(dst, r.cfg)
case config.FilterDifference: case config.FilterDifference:
r.filters[i] = filter.NewDifference(dst, r.cfg.DiffThreshold) r.filters[i] = filter.NewDifference(dst, r.cfg)
case config.FilterBasic: case config.FilterBasic:
r.filters[i] = filter.NewBasic(dst, r.cfg.BasicThreshold, r.cfg.BasicPixels) r.filters[i] = filter.NewBasic(dst, r.cfg)
default: default:
panic("Undefined Filter") panic("Undefined Filter")
} }
@ -685,13 +685,6 @@ func (r *Revid) Update(vars map[string]string) error {
} }
r.cfg.Filters[i] = v r.cfg.Filters[i] = v
} }
case "MotionInterval":
v, err := strconv.Atoi(value)
if err != nil || v < 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionInterval var", "value", value)
break
}
r.cfg.MotionInterval = v
case "PSITime": case "PSITime":
v, err := strconv.Atoi(value) v, err := strconv.Atoi(value)
if err != nil || v < 0 { if err != nil || v < 0 {
@ -800,77 +793,55 @@ func (r *Revid) Update(vars map[string]string) error {
break break
} }
r.cfg.MinFPS = v r.cfg.MinFPS = v
case "KNNMinArea": case "MotionMinArea":
v, err := strconv.ParseFloat(value, 64) v, err := strconv.ParseFloat(value, 64)
if err != nil { if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNMinArea var", "value", value) r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionMinArea var", "value", value)
break break
} }
r.cfg.KNNMinArea = v r.cfg.MotionMinArea = v
case "KNNThreshold": case "MotionThreshold":
v, err := strconv.ParseFloat(value, 64) v, err := strconv.ParseFloat(value, 64)
if err != nil { if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNThreshold var", "value", value) r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionThreshold var", "value", value)
break break
} }
r.cfg.KNNThreshold = v r.cfg.MotionThreshold = v
case "DiffThreshold": case "MotionKernel":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid DiffThreshold var", "value", value)
break
}
r.cfg.DiffThreshold = v
case "KNNKernel":
v, err := strconv.Atoi(value) v, err := strconv.Atoi(value)
if err != nil { if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNKernel var", "value", value) r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionKernel var", "value", value)
break break
} }
r.cfg.KNNKernel = uint(v) r.cfg.MotionKernel = uint(v)
case "MOGMinArea": case "MotionHistory":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MOGMinArea var", "value", value)
break
}
r.cfg.MOGMinArea = v
case "MOGThreshold":
v, err := strconv.ParseFloat(value, 64)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MOGThreshold var", "value", value)
break
}
r.cfg.MOGThreshold = v
case "KNNHistory":
v, err := strconv.Atoi(value) v, err := strconv.Atoi(value)
if err != nil || v <= 0 { if err != nil || v <= 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid KNNHistory var", "value", value) r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionHistory var", "value", value)
break break
} }
r.cfg.KNNHistory = uint(v) r.cfg.MotionHistory = uint(v)
case "MOGHistory": case "MotionPixels":
v, err := strconv.Atoi(value)
if err != nil || v <= 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MOGHistory var", "value", value)
break
}
r.cfg.MOGHistory = uint(v)
case "BasicThreshold":
v, err := strconv.Atoi(value) v, err := strconv.Atoi(value)
if err != nil { if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid BasicThreshold var", "value", value) r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionPixels var", "value", value)
break break
} }
r.cfg.BasicThreshold = v r.cfg.MotionPixels = v
case "BasicPixels": case "MotionDownscaling":
v, err := strconv.Atoi(value) v, err := strconv.Atoi(value)
if err != nil { if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid BasicPixels var", "value", value) r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionDownscaling var", "value", value)
break break
} }
r.cfg.BasicPixels = v r.cfg.MotionDownscaling = v
case "MotionInterval":
v, err := strconv.Atoi(value)
if err != nil || v < 0 {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionInterval var", "value", value)
break
}
r.cfg.MotionInterval = v
case "FileFPS": case "FileFPS":
v, err := strconv.Atoi(value) v, err := strconv.Atoi(value)
if err != nil { if err != nil {
@ -883,13 +854,6 @@ func (r *Revid) Update(vars map[string]string) error {
if value == "Loop" { if value == "Loop" {
r.cfg.Loop = true r.cfg.Loop = true
} }
case "MotionDownscaling":
v, err := strconv.Atoi(value)
if err != nil {
r.cfg.Logger.Log(logger.Warning, pkg+"invalid MotionDownscaling var", "value", value)
break
}
r.cfg.MotionDownscaling = v
} }
} }
r.cfg.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.cfg)) r.cfg.Logger.Log(logger.Info, pkg+"revid config changed", "config", fmt.Sprintf("%+v", r.cfg))