mirror of https://bitbucket.org/ausocean/av.git
filter: add option to reduce resolution of frames for MOG motion filter
A new netsender variable, FilterDownscaling is used for reducing the resolution of frames within the MOG motion filter. This does not affect the resolution of the video output, it is only used to speed up calculations. A FilterDownscaling factor of 2 is equivalent to skipping every 2nd pixel in the image.
This commit is contained in:
parent
c90cc40949
commit
10bfc296be
|
@ -32,7 +32,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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, debug bool, hf int) *NoOp {
|
func NewMOG(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int, downscalingFactor int) *NoOp {
|
||||||
return &NoOp{dst: dst}
|
return &NoOp{dst: dst}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,17 +49,18 @@ type MOG struct {
|
||||||
hold [][]byte // Will hold all frames up to hf (so only every hf frame is motion detected).
|
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.
|
hf int // The number of frames to be held.
|
||||||
hfCount int // Counter for the hold array.
|
hfCount int // Counter for the hold array.
|
||||||
|
scale float64 // The factor that frames will be downscaled by for motion detection.
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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, debug bool, hf int) *MOG {
|
func NewMOG(dst io.WriteCloser, area, threshold float64, history int, debug bool, hf int, downscalingFactor int) *MOG {
|
||||||
bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false)
|
bs := gocv.NewBackgroundSubtractorMOG2WithParams(history, threshold, false)
|
||||||
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3))
|
k := gocv.GetStructuringElement(gocv.MorphRect, image.Pt(3, 3))
|
||||||
var windows []*gocv.Window
|
var windows []*gocv.Window
|
||||||
if debug {
|
if debug {
|
||||||
windows = []*gocv.Window{gocv.NewWindow("MOG: Bounding boxes"), gocv.NewWindow("MOG: Motion")}
|
windows = []*gocv.Window{gocv.NewWindow("MOG: Bounding boxes"), gocv.NewWindow("MOG: Motion")}
|
||||||
}
|
}
|
||||||
return &MOG{dst, area, &bs, k, debug, windows, make([][]byte, hf-1), hf, 0}
|
return &MOG{dst, area, &bs, k, debug, windows, make([][]byte, hf-1), hf, 0, 1 / float64(downscalingFactor)}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Implements io.Closer.
|
// Implements io.Closer.
|
||||||
|
@ -94,6 +95,9 @@ func (m *MOG) Write(f []byte) (int, error) {
|
||||||
imgDelta := gocv.NewMat()
|
imgDelta := gocv.NewMat()
|
||||||
defer imgDelta.Close()
|
defer imgDelta.Close()
|
||||||
|
|
||||||
|
// Downsize image to speed up calculations.
|
||||||
|
gocv.Resize(img, &img, image.Point{}, m.scale, m.scale, gocv.InterpolationNearestNeighbor)
|
||||||
|
|
||||||
// Seperate foreground and background.
|
// Seperate foreground and background.
|
||||||
m.bs.Apply(img, &imgDelta)
|
m.bs.Apply(img, &imgDelta)
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,6 @@ const (
|
||||||
defaultClipDuration = 0
|
defaultClipDuration = 0
|
||||||
defaultAudioInputCodec = codecutil.ADPCM
|
defaultAudioInputCodec = codecutil.ADPCM
|
||||||
defaultPSITime = 2
|
defaultPSITime = 2
|
||||||
defaultMotionInterval = 5
|
|
||||||
defaultFileFPS = 0
|
defaultFileFPS = 0
|
||||||
|
|
||||||
// Ring buffer defaults.
|
// Ring buffer defaults.
|
||||||
|
@ -95,6 +94,8 @@ const (
|
||||||
|
|
||||||
// Motion filter parameter defaults.
|
// Motion filter parameter defaults.
|
||||||
defaultMinFPS = 1.0
|
defaultMinFPS = 1.0
|
||||||
|
defaultMotionDownscaling = 1
|
||||||
|
defaultMotionInterval = 1
|
||||||
|
|
||||||
// KNN filter parameter defaults.
|
// KNN filter parameter defaults.
|
||||||
defaultKNNMinArea = 25.0
|
defaultKNNMinArea = 25.0
|
||||||
|
@ -283,7 +284,6 @@ type Config struct {
|
||||||
HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input.
|
HorizontalFlip bool // HorizontalFlip flips video horizontally for Raspivid input.
|
||||||
VerticalFlip bool // VerticalFlip flips video vertically 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.
|
Filters []int // Defines the methods of filtering to be used in between lexing and encoding.
|
||||||
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.
|
PSITime int // Sets the time between a packet being sent.
|
||||||
|
|
||||||
// Ring buffer parameters.
|
// Ring buffer parameters.
|
||||||
|
@ -293,6 +293,8 @@ type Config struct {
|
||||||
|
|
||||||
// Motion filter parameters.
|
// Motion filter parameters.
|
||||||
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)
|
||||||
|
MotionDownscaling int // Downscaling factor of frames used for motion detection.
|
||||||
|
|
||||||
// KNN filter parameters.
|
// KNN filter parameters.
|
||||||
KNNMinArea float64 // Used to ignore small areas of motion detection.
|
KNNMinArea float64 // Used to ignore small areas of motion detection.
|
||||||
|
@ -303,8 +305,12 @@ type Config struct {
|
||||||
// MOG filter parameters.
|
// MOG filter parameters.
|
||||||
MOGMinArea float64 // Used to ignore small areas of motion detection.
|
MOGMinArea float64 // Used to ignore small areas of motion detection.
|
||||||
MOGThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
|
MOGThreshold float64 // Intensity value from the KNN motion detection algorithm that is considered motion.
|
||||||
MOGHistory uint // Length of MOG filter's history
|
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
|
BasicThreshold int
|
||||||
BasicPixels int
|
BasicPixels int
|
||||||
|
|
||||||
|
@ -313,8 +319,6 @@ type Config struct {
|
||||||
|
|
||||||
// Defines the rate at which frames from a file source are processed.
|
// Defines the rate at which frames from a file source are processed.
|
||||||
FileFPS int
|
FileFPS int
|
||||||
// Difference filter parameters.
|
|
||||||
DiffThreshold float64 // Intensity value from the Difference motion detection algorithm that is considered motion.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TypeData contains information about all of the variables that
|
// TypeData contains information about all of the variables that
|
||||||
|
@ -353,6 +357,7 @@ var TypeData = map[string]string{
|
||||||
"MOGHistory": "uint",
|
"MOGHistory": "uint",
|
||||||
"MOGMinArea": "float",
|
"MOGMinArea": "float",
|
||||||
"MOGThreshold": "float",
|
"MOGThreshold": "float",
|
||||||
|
"MotionDownscaling": "uint",
|
||||||
"MotionInterval": "int",
|
"MotionInterval": "int",
|
||||||
"Output": "enum:File,Http,Rtmp,Rtp",
|
"Output": "enum:File,Http,Rtmp,Rtp",
|
||||||
"OutputPath": "string",
|
"OutputPath": "string",
|
||||||
|
@ -544,6 +549,11 @@ func (c *Config) Validate() error {
|
||||||
c.BasicPixels = defaultBasicPixels
|
c.BasicPixels = defaultBasicPixels
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.MotionDownscaling <= 0 {
|
||||||
|
c.logInvalidField("MotionDownscaling", defaultMotionDownscaling)
|
||||||
|
c.MotionDownscaling = defaultMotionDownscaling
|
||||||
|
}
|
||||||
|
|
||||||
if c.ShowWindows {
|
if c.ShowWindows {
|
||||||
os, err := osName()
|
os, err := osName()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -341,9 +341,9 @@ 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.ShowWindows, r.cfg.MotionInterval)
|
r.filters[i] = filter.NewMOG(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.ShowWindows, r.cfg.MotionInterval, r.cfg.MotionDownscaling)
|
||||||
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.ShowWindows, r.cfg.MotionInterval))
|
r.filters[i] = filter.NewVariableFPS(dst, r.cfg.MinFPS, filter.NewMOG(dst, r.cfg.MOGMinArea, r.cfg.MOGThreshold, int(r.cfg.MOGHistory), r.cfg.ShowWindows, r.cfg.MotionInterval, r.cfg.MotionDownscaling))
|
||||||
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.ShowWindows, r.cfg.MotionInterval)
|
r.filters[i] = filter.NewKNN(dst, r.cfg.KNNMinArea, r.cfg.KNNThreshold, int(r.cfg.KNNHistory), int(r.cfg.KNNKernel), r.cfg.ShowWindows, r.cfg.MotionInterval)
|
||||||
case config.FilterDifference:
|
case config.FilterDifference:
|
||||||
|
@ -904,6 +904,13 @@ 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))
|
||||||
|
|
Loading…
Reference in New Issue