
/*
背景统计模型
作者:王先荣
时间:2010年2月19日
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Diagnostics;
using System.Runtime.InteropServices;
using Emgu.CV;
using Emgu.CV.CvEnum;
using Emgu.CV.Structure;
using Emgu.CV.UI;
using Emgu.CV.VideoSurveillance;
namespace ImageProcessLearn
{
//背景模型接口,在IBGFGDetector接口的基础上增加了一个CurrentFrame属性
public interface IBackgroundStatModel<TColor> : IDisposable
where TColor : struct, IColor
{
/// <summary>
/// 获取前景
/// </summary>
Image<Gray, byte> BackgroundMask { get; }
/// <summary>
/// 获取背景
/// </summary>
Image<Gray, byte> ForegroundMask { get; }
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
void Update(Image<TColor, byte> image);
/// <summary>
/// 计算统计数据
/// </summary>
void CalcStatData();
/// <summary>
/// 获取或者设置当前帧
/// </summary>
Image<TColor, Byte> CurrentFrame
{
get;
set;
}
}
/// <summary>
/// 使用帧差的方式来建立背景模型
/// </summary>
/// <typeparam name="TColor"></typeparam>
public class BackgroundStatModelFrameDiff<TColor> : IBackgroundStatModel<TColor>
where TColor : struct, IColor
{
//成员
private Image<TColor, Byte> imageBackgroundModel; //背景模型图像
private Image<TColor, Byte> currentFrame; //当前帧
private double threshold; //计算前景时所用的阀值,如果当前帧和背景的差别大于阀值,则被认为是前景
private Image<Gray, Byte> backgroundMask; //计算得到的背景图像
/// <summary>
/// 构造函数
/// </summary>
/// <param name="image">用于背景统计模型的背景</param>
public BackgroundStatModelFrameDiff(Image<TColor, Byte> image)
{
imageBackgroundModel = image;
currentFrame = null;
threshold = 15d;
backgroundMask = null;
}
public BackgroundStatModelFrameDiff()
: this(null)
{
}
/// <summary>
/// 设置或者获取计算前景时所用的阀值;如果阀值为0,则使用自适应的阀值
/// </summary>
public double Threshold
{
get
{
return threshold;
}
set
{
threshold = value >= 0 ? value : 15d;
}
}
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
public void Update(Image<TColor, Byte> image)
{
imageBackgroundModel = image;
}
/// <summary>
/// 获取或者设置当前帧
/// </summary>
public Image<TColor, Byte> CurrentFrame
{
get
{
return currentFrame;
}
set
{
currentFrame = value;
CalcBackgroundMask();
}
}
/// <summary>
/// 计算统计数据
/// </summary>
public void CalcStatData()
{
}
/// <summary>
/// 计算背景
/// </summary>
private void CalcBackgroundMask()
{
if (imageBackgroundModel == null || currentFrame == null || imageBackgroundModel.Size != currentFrame.Size)
throw new ArgumentException("在计算背景时发现参数错误。可能是:背景模型图像为空,当前帧为空,或者背景模型图像和当前帧的尺寸不一致。");
if (backgroundMask == null)
backgroundMask = new Image<Gray, byte>(imageBackgroundModel.Size);
if (threshold == 0d)
//如果阀值为0,使用OpenCv中的自适应动态背景检测
OpenCvInvoke.cvChangeDetection(imageBackgroundModel.Ptr, currentFrame.Ptr, backgroundMask.Ptr);
else
{
//如果设置了阀值,使用帧差
Image<TColor, Byte> imageTemp = imageBackgroundModel.AbsDiff(currentFrame);
Image<Gray, Byte>[] images = imageTemp.Split();
backgroundMask.SetValue(0d);
foreach (Image<Gray, Byte> image in images)
backgroundMask._Or(image.ThresholdBinary(new Gray(threshold), new Gray(255d)));
}
backgroundMask._Not();
}
/// <summary>
/// 获取背景
/// </summary>
public Image<Gray, Byte> BackgroundMask
{
get
{
return backgroundMask;
}
}
/// <summary>
/// 获取前景
/// </summary>
public Image<Gray, Byte> ForegroundMask
{
get
{
return backgroundMask.Not();
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (backgroundMask != null)
backgroundMask.Dispose();
}
}
/// <summary>
/// 使用平均背景来建立背景模型
/// </summary>
/// <typeparam name="TColor"></typeparam>
public class BackgroundStatModelAccAvg<TColor> : IBackgroundStatModel<TColor>
where TColor : struct, IColor
{
//成员
private Image<TColor, Single> imageAccSum; //累计图像
private Image<TColor, Single> imageAccDiff; //累计差值图像
private int frameCount; //已经累计的背景帧数
private Image<TColor, Single> previousFrame; //在背景建模时使用的前一帧图像
private Image<TColor, Byte> currentFrame; //当前帧图像
private double scale; //计算背景时所使用的缩放系数,大于平均值*scale倍数的像素认为是前景
private Image<Gray, Byte> backgroundMask; //计算得到的背景图像
private Image<TColor, Single> imageTemp; //临时图像
private bool isStatDataReady; //是否已经准备好统计数据
private Image<Gray, Single>[] imagesHi; //背景模型中各通道的最大值图像
private Image<Gray, Single>[] imagesLow; //背景模型中各通道的最小值图像
/// <summary>
/// 构造函数
/// </summary>
public BackgroundStatModelAccAvg()
{
imageAccSum = null;
imageAccDiff = null;
frameCount = 0;
previousFrame = null;
currentFrame = null;
scale = 6d;
backgroundMask = null;
isStatDataReady = false;
imagesHi = null;
imagesLow = null;
}
/// <summary>
/// 设置或者获取计算前景时所用的阀值
/// </summary>
public double Scale
{
get
{
return scale;
}
set
{
scale = value > 0 ? value : 6d;
}
}
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
public void Update(Image<TColor, Byte> image)
{
if (frameCount==0)
{
imageAccSum = new Image<TColor, Single>(image.Size);
imageAccSum.SetValue(0d);
imageAccDiff = new Image<TColor, float>(image.Size);
imageAccDiff.SetValue(0d);
}
imageTemp = image.ConvertScale<Single>(1d, 0d); //将图像转换成浮点型
imageAccSum.Acc(imageTemp);
if (previousFrame != null)
imageAccDiff.Acc(imageTemp.AbsDiff(previousFrame));
previousFrame = imageTemp.Copy();
frameCount++;
}
/// <summary>
/// 获取或者设置当前帧
/// </summary>
public Image<TColor, Byte> CurrentFrame
{
get
{
return currentFrame;
}
set
{
currentFrame = value;
CalcBackgroundMask();
}
}
/// <summary>
/// 计算统计数据
/// </summary>
public void CalcStatData()
{
//计算出最高及最低阀值图像
Image<TColor, Single> imageAvg = imageAccSum.ConvertScale<Single>(1d / frameCount, 0d);
Image<TColor, Single> imageAvgDiff = imageAccDiff.ConvertScale<Single>(1d / frameCount, 1d); //将平均值加1,为了确保总是存在差异
Image<TColor, Single> imageHi = imageAvg.Add(imageAvgDiff.ConvertScale<Single>(scale, 0d));
Image<TColor, Single> imageLow = imageAvg.Sub(imageAvgDiff.ConvertScale<Single>(scale, 0d));
imagesHi = imageHi.Split();
imagesLow = imageLow.Split();
isStatDataReady = true;
//释放资源
imageAvg.Dispose();
imageAvgDiff.Dispose();
imageHi.Dispose();
imageLow.Dispose();
}
/// <summary>
/// 计算背景
/// </summary>
private void CalcBackgroundMask()
{
if (imageAccSum == null || imageAccDiff == null || imageAccSum.Size != currentFrame.Size)
throw new ArgumentException("在计算背景时发生参数错误。可能是:还没有建立背景模型;或者当前帧的尺寸与背景尺寸不一致。");
if (!isStatDataReady)
CalcStatData();
imageTemp = currentFrame.ConvertScale<Single>(1d, 0d);
Image<Gray, Single>[] images = imageTemp.Split();
//计算背景图像
if (backgroundMask == null)
backgroundMask = new Image<Gray, byte>(currentFrame.Size);
backgroundMask.SetZero();
for (int i = 0; i < currentFrame.NumberOfChannels; i++)
backgroundMask._Or(images[i].InRange(imagesLow[i], imagesHi[i]));
//释放资源
for (int i = 0; i < images.Length; i++)
images[i].Dispose();
}
/// <summary>
/// 获取背景
/// </summary>
public Image<Gray, Byte> BackgroundMask
{
get
{
return backgroundMask;
}
}
/// <summary>
/// 获取前景
/// </summary>
public Image<Gray, Byte> ForegroundMask
{
get
{
return backgroundMask.Not();
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (imageAccSum != null)
imageAccSum.Dispose();
if (imageAccDiff != null)
imageAccDiff.Dispose();
if (previousFrame != null)
previousFrame.Dispose();
if (currentFrame != null)
currentFrame.Dispose();
if (backgroundMask != null)
backgroundMask.Dispose();
if (isStatDataReady)
{
for (int i = 0; i < imagesHi.Length; i++)
{
imagesHi[i].Dispose();
imagesLow[i].Dispose();
}
}
}
}
/// <summary>
/// 使用均值漂移来建立背景模型
/// </summary>
/// <typeparam name="TColor"></typeparam>
public class BackgroundStatModelRunningAvg<TColor> : IBackgroundStatModel<TColor>
where TColor : struct, IColor
{
//成员
private Image<TColor, Single> imageAcc; //累计图像
private Image<TColor, Single> imageAccDiff; //累计差值图像
private int frameCount; //已经累计的背景帧数
private Image<TColor, Single> previousFrame; //在背景建模时使用的前一帧图像
private Image<TColor, Byte> currentFrame; //当前帧图像
private double scale; //计算背景时所使用的缩放系数,大于平均值*scale倍数的像素认为是前景
private double alpha; //计算均值漂移时使用的权值
private Image<Gray, Byte> backgroundMask; //计算得到的背景图像
private Image<TColor, Single> imageTemp; //临时图像
private bool isStatDataReady; //是否已经准备好统计数据
private Image<Gray, Single>[] imagesHi; //背景模型中各通道的最大值图像
private Image<Gray, Single>[] imagesLow; //背景模型中各通道的最小值图像
/// <summary>
/// 构造函数
/// </summary>
public BackgroundStatModelRunningAvg()
{
imageAcc = null;
imageAccDiff = null;
frameCount = 0;
previousFrame = null;
currentFrame = null;
scale = 6d;
alpha = 0.5d;
backgroundMask = null;
isStatDataReady = false;
imagesHi = null;
imagesLow = null;
}
/// <summary>
/// 设置或者获取计算前景时所用的阀值
/// </summary>
public double Scale
{
get
{
return scale;
}
set
{
scale = value > 0 ? value : 6d;
}
}
/// <summary>
/// 设置或者获取计算均值漂移是使用的权值
/// </summary>
public double Alpha
{
get
{
return alpha;
}
set
{
alpha = value > 0 && value < 1 ? value : 0.5d;
}
}
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
public void Update(Image<TColor, Byte> image)
{
imageTemp = image.ConvertScale<Single>(1d, 0d); //将图像转换成浮点型
if (imageAcc == null)
{
imageAcc = imageTemp.Copy();
}
else
imageAcc.RunningAvg(imageTemp, alpha);
if (previousFrame != null)
{
if (imageAccDiff == null)
imageAccDiff = imageTemp.AbsDiff(previousFrame);
else
imageAccDiff.RunningAvg(imageTemp.AbsDiff(previousFrame), alpha);
}
previousFrame = imageTemp.Copy();
frameCount++;
}
/// <summary>
/// 获取或者设置当前帧
/// </summary>
public Image<TColor, Byte> CurrentFrame
{
get
{
return currentFrame;
}
set
{
currentFrame = value;
CalcBackgroundMask();
}
}
/// <summary>
/// 计算统计数据
/// </summary>
public void CalcStatData()
{
//计算出最高及最低阀值图像
Image<TColor, Single> imageHi = imageAcc.Add(imageAccDiff.ConvertScale<Single>(scale, 0d));
Image<TColor, Single> imageLow = imageAcc.Sub(imageAccDiff.ConvertScale<Single>(scale, 0d));
imagesHi = imageHi.Split();
imagesLow = imageLow.Split();
isStatDataReady = true;
//释放资源
imageHi.Dispose();
imageLow.Dispose();
}
/// <summary>
/// 计算背景
/// </summary>
private void CalcBackgroundMask()
{
if (imageAcc == null || imageAccDiff == null || imageAcc.Size != currentFrame.Size)
throw new ArgumentException("在计算背景时发生参数错误。可能是:还没有建立背景模型;或者当前帧的尺寸与背景尺寸不一致。");
if (!isStatDataReady)
CalcStatData();
imageTemp = currentFrame.ConvertScale<Single>(1d, 0d);
Image<Gray, Single>[] images = imageTemp.Split();
//计算背景图像
if (backgroundMask == null)
backgroundMask = new Image<Gray, byte>(currentFrame.Size);
backgroundMask.SetZero();
for (int i = 0; i < currentFrame.NumberOfChannels; i++)
backgroundMask._Or(images[i].InRange(imagesLow[i], imagesHi[i]));
//释放资源
for (int i = 0; i < images.Length; i++)
images[i].Dispose();
}
/// <summary>
/// 获取背景
/// </summary>
public Image<Gray, Byte> BackgroundMask
{
get
{
return backgroundMask;
}
}
/// <summary>
/// 获取前景
/// </summary>
public Image<Gray, Byte> ForegroundMask
{
get
{
return backgroundMask.Not();
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (imageAcc != null)
imageAcc.Dispose();
if (imageAccDiff != null)
imageAccDiff.Dispose();
if (previousFrame != null)
previousFrame.Dispose();
if (currentFrame != null)
currentFrame.Dispose();
if (backgroundMask != null)
backgroundMask.Dispose();
if (isStatDataReady)
{
for (int i = 0; i < imagesHi.Length; i++)
{
imagesHi[i].Dispose();
imagesLow[i].Dispose();
}
}
}
}
/// <summary>
/// 使用标准方差来建立背景模型
/// </summary>
/// <typeparam name="TColor"></typeparam>
public class BackgroundStatModelSquareAcc<TColor> : IBackgroundStatModel<TColor>
where TColor : struct, IColor
{
//成员
private Image<TColor, Single> imageAccSum; //累计图像
private Image<TColor, Single> imageAccSquare; //累计平方图像
private int frameCount; //已经累计的背景帧数
private Image<TColor, Single> previousFrame; //在背景建模时使用的前一帧图像
private Image<TColor, Byte> currentFrame; //当前帧图像
private double scale; //计算背景时所使用的缩放系数,大于平均值*scale倍数的像素认为是前景
private Image<Gray, Byte> backgroundMask; //计算得到的背景图像
private Image<TColor, Single> imageTemp; //临时图像
private bool isStatDataReady; //是否已经准备好统计数据
private Image<Gray, Single>[] imagesHi; //背景模型中各通道的最大值图像
private Image<Gray, Single>[] imagesLow; //背景模型中各通道的最小值图像
/// <summary>
/// 构造函数
/// </summary>
public BackgroundStatModelSquareAcc()
{
imageAccSum = null;
imageAccSquare = null;
frameCount = 0;
previousFrame = null;
currentFrame = null;
scale = 6d;
backgroundMask = null;
isStatDataReady = false;
imagesHi = null;
imagesLow = null;
}
/// <summary>
/// 设置或者获取计算前景时所用的阀值
/// </summary>
public double Scale
{
get
{
return scale;
}
set
{
scale = value > 0 ? value : 6d;
}
}
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
public void Update(Image<TColor, Byte> image)
{
if (frameCount == 0)
{
imageAccSum = new Image<TColor, Single>(image.Size);
imageAccSum.SetZero();
imageAccSquare = new Image<TColor, float>(image.Size);
imageAccSquare.SetZero();
}
imageTemp = image.ConvertScale<Single>(1d, 0d); //将图像转换成浮点型
imageAccSum.Acc(imageTemp);
CvInvoke.cvSquareAcc(imageTemp.Ptr, imageAccSquare.Ptr, IntPtr.Zero);
previousFrame = imageTemp.Copy();
frameCount++;
}
/// <summary>
/// 获取或者设置当前帧
/// </summary>
public Image<TColor, Byte> CurrentFrame
{
get
{
return currentFrame;
}
set
{
currentFrame = value;
CalcBackgroundMask();
}
}
/// <summary>
/// 计算统计数据
/// </summary>
public void CalcStatData()
{
//计算出标准差、最高及最低阀值图像
Image<TColor, Single> imageAvg = imageAccSum.ConvertScale<Single>(1d / frameCount, 0d);
Image<TColor, Single> imageSd = imageAccSquare.ConvertScale<Single>(1d / frameCount, 0d);
imageSd.Sub(imageAvg.Pow(2d));
imageSd = imageSd.Pow(0.5d);
Image<TColor, Single> imageHi = imageAvg.Add(imageSd.ConvertScale<Single>(scale, 0d));
Image<TColor, Single> imageLow = imageAvg.Sub(imageSd.ConvertScale<Single>(scale, 0d));
imagesHi = imageHi.Split();
imagesLow = imageLow.Split();
isStatDataReady = true;
//释放资源
imageAvg.Dispose();
imageSd.Dispose();
imageHi.Dispose();
imageLow.Dispose();
}
/// <summary>
/// 计算背景
/// </summary>
private void CalcBackgroundMask()
{
if (imageAccSum == null || imageAccSquare == null || imageAccSum.Size != currentFrame.Size)
throw new ArgumentException("在计算背景时发生参数错误。可能是:还没有建立背景模型;或者当前帧的尺寸与背景尺寸不一致。");
if (!isStatDataReady)
CalcStatData();
imageTemp = currentFrame.ConvertScale<Single>(1d, 0d);
Image<Gray, Single>[] images = imageTemp.Split();
//计算背景图像
if (backgroundMask == null)
backgroundMask = new Image<Gray, byte>(currentFrame.Size);
backgroundMask.SetZero();
for (int i = 0; i < currentFrame.NumberOfChannels; i++)
backgroundMask._Or(images[i].InRange(imagesLow[i], imagesHi[i]));
//释放资源
for (int i = 0; i < images.Length; i++)
images[i].Dispose();
}
/// <summary>
/// 获取背景
/// </summary>
public Image<Gray, Byte> BackgroundMask
{
get
{
return backgroundMask;
}
}
/// <summary>
/// 获取前景
/// </summary>
public Image<Gray, Byte> ForegroundMask
{
get
{
return backgroundMask.Not();
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (imageAccSum != null)
imageAccSum.Dispose();
if (imageAccSquare != null)
imageAccSquare.Dispose();
if (previousFrame != null)
previousFrame.Dispose();
if (currentFrame != null)
currentFrame.Dispose();
if (backgroundMask != null)
backgroundMask.Dispose();
if (isStatDataReady)
{
for (int i = 0; i < imagesHi.Length; i++)
{
imagesHi[i].Dispose();
imagesLow[i].Dispose();
}
}
}
}
/// <summary>
/// 使用标准协方差来建立背景模型
/// </summary>
/// <typeparam name="TColor"></typeparam>
public class BackgroundStatModelMultiplyAcc<TColor> : IBackgroundStatModel<TColor>
where TColor : struct, IColor
{
//成员
private Image<TColor, Single> imageAccSum; //累计图像
private Image<TColor, Single> imageAccMultiply; //累计平方图像
private int frameCount; //已经累计的背景帧数
private Image<TColor, Single> previousFrame; //在背景建模时使用的前一帧图像
private Image<TColor, Byte> currentFrame; //当前帧图像
private double scale; //计算背景时所使用的缩放系数,大于平均值*scale倍数的像素认为是前景
private Image<Gray, Byte> backgroundMask; //计算得到的背景图像
private Image<TColor, Single> imageTemp; //临时图像
private bool isStatDataReady; //是否已经准备好统计数据
private Image<Gray, Single>[] imagesHi; //背景模型中各通道的最大值图像
private Image<Gray, Single>[] imagesLow; //背景模型中各通道的最小值图像
/// <summary>
/// 构造函数
/// </summary>
public BackgroundStatModelMultiplyAcc()
{
imageAccSum = null;
imageAccMultiply = null;
frameCount = 0;
previousFrame = null;
currentFrame = null;
scale = 6d;
backgroundMask = null;
isStatDataReady = false;
imagesHi = null;
imagesLow = null;
}
/// <summary>
/// 设置或者获取计算前景时所用的阀值
/// </summary>
public double Scale
{
get
{
return scale;
}
set
{
scale = value > 0 ? value : 6d;
}
}
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
public void Update(Image<TColor, Byte> image)
{
if (frameCount == 0)
{
imageAccSum = new Image<TColor, Single>(image.Size);
imageAccSum.SetZero();
imageAccMultiply = new Image<TColor, float>(image.Size);
imageAccMultiply.SetZero();
}
imageTemp = image.ConvertScale<Single>(1d, 0d); //将图像转换成浮点型
imageAccSum.Acc(imageTemp);
if (previousFrame != null)
CvInvoke.cvMultiplyAcc(previousFrame.Ptr, imageTemp.Ptr, imageAccMultiply.Ptr, IntPtr.Zero);
previousFrame = imageTemp.Copy();
frameCount++;
}
/// <summary>
/// 获取或者设置当前帧
/// </summary>
public Image<TColor, Byte> CurrentFrame
{
get
{
return currentFrame;
}
set
{
currentFrame = value;
CalcBackgroundMask();
}
}
/// <summary>
/// 计算统计数据
/// </summary>
public void CalcStatData()
{
//计算出标准协方差、最高及最低阀值图像
Image<TColor, Single> imageAvg = imageAccSum.ConvertScale<Single>(1d / frameCount, 0d);
Image<TColor, Single> imageScov = imageAccMultiply.ConvertScale<Single>(1d / frameCount, 0d);
imageScov.Sub(imageAvg.Pow(2d));
imageScov = imageScov.Pow(0.5d);
Image<TColor, Single> imageHi = imageAvg.Add(imageScov.ConvertScale<Single>(scale, 0d));
Image<TColor, Single> imageLow = imageAvg.Sub(imageScov.ConvertScale<Single>(scale, 0d));
imagesHi = imageHi.Split();
imagesLow = imageLow.Split();
isStatDataReady = true;
//释放资源
imageAvg.Dispose();
imageScov.Dispose();
imageHi.Dispose();
imageLow.Dispose();
}
/// <summary>
/// 计算背景
/// </summary>
private void CalcBackgroundMask()
{
if (imageAccSum == null || imageAccMultiply == null || imageAccSum.Size != currentFrame.Size)
throw new ArgumentException("在计算背景时发生参数错误。可能是:还没有建立背景模型;或者当前帧的尺寸与背景尺寸不一致。");
if (!isStatDataReady)
CalcStatData();
imageTemp = currentFrame.ConvertScale<Single>(1d, 0d);
Image<Gray, Single>[] images = imageTemp.Split();
//计算背景图像
if (backgroundMask == null)
backgroundMask = new Image<Gray, byte>(currentFrame.Size);
backgroundMask.SetZero();
for (int i = 0; i < currentFrame.NumberOfChannels; i++)
backgroundMask._Or(images[i].InRange(imagesLow[i], imagesHi[i]));
//释放资源
for (int i = 0; i < images.Length; i++)
images[i].Dispose();
}
/// <summary>
/// 获取背景
/// </summary>
public Image<Gray, Byte> BackgroundMask
{
get
{
return backgroundMask;
}
}
/// <summary>
/// 获取前景
/// </summary>
public Image<Gray, Byte> ForegroundMask
{
get
{
return backgroundMask.Not();
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (imageAccSum != null)
imageAccSum.Dispose();
if (imageAccMultiply != null)
imageAccMultiply.Dispose();
if (previousFrame != null)
previousFrame.Dispose();
if (currentFrame != null)
currentFrame.Dispose();
if (backgroundMask != null)
backgroundMask.Dispose();
if (isStatDataReady)
{
for (int i = 0; i < imagesHi.Length; i++)
{
imagesHi[i].Dispose();
imagesLow[i].Dispose();
}
}
}
}
/// <summary>
/// 背景统计模型
/// </summary>
public class BackgroundStatModelBase<TColor> : IBackgroundStatModel<TColor>
where TColor : struct, IColor
{
//成员变量
IBackgroundStatModel<TColor> bgModel;
BackgroundStatModelType type;
/// <summary>
/// 构造函数
/// </summary>
/// <param name="type">背景模型类型</param>
public BackgroundStatModelBase(BackgroundStatModelType type)
{
this.type = type;
switch (type)
{
case BackgroundStatModelType.FrameDiff:
bgModel = new BackgroundStatModelFrameDiff<TColor>();
break;
case BackgroundStatModelType.AccAvg:
bgModel = new BackgroundStatModelAccAvg<TColor>();
break;
case BackgroundStatModelType.RunningAvg:
bgModel = new BackgroundStatModelRunningAvg<TColor>();
break;
case BackgroundStatModelType.SquareAcc:
bgModel = new BackgroundStatModelSquareAcc<TColor>();
break;
case BackgroundStatModelType.MultiplyAcc:
bgModel = new BackgroundStatModelMultiplyAcc<TColor>();
break;
default:
throw new ArgumentException("不存在的背景模型", "type");
}
}
/// <summary>
/// 获取背景模型类型
/// </summary>
public BackgroundStatModelType BackgroundStatModelType
{
get
{
return type;
}
}
/// <summary>
/// 更新背景模型
/// </summary>
/// <param name="image"></param>
public void Update(Image<TColor, Byte> image)
{
bgModel.Update(image);
}
/// <summary>
/// 计算统计数据
/// </summary>
public void CalcStatData()
{
bgModel.CalcStatData();
}
/// <summary>
/// 设置或者获取当前帧
/// </summary>
public Image<TColor, Byte> CurrentFrame
{
get
{
return bgModel.CurrentFrame;
}
set
{
bgModel.CurrentFrame = value;
}
}
/// <summary>
/// 获取背景
/// </summary>
public Image<Gray, Byte> BackgroundMask
{
get
{
return bgModel.BackgroundMask;
}
}
/// <summary>
/// 获取前景
/// </summary>
public Image<Gray, Byte> ForegroundMask
{
get
{
return bgModel.ForegroundMask;
}
}
/// <summary>
/// 释放资源
/// </summary>
public void Dispose()
{
if (bgModel != null)
bgModel.Dispose();
}
}
/// <summary>
/// 背景模型类型
/// </summary>
public enum BackgroundStatModelType
{
FrameDiff, //帧差
AccAvg, //平均背景
RunningAvg, //均值漂移
MultiplyAcc, //计算协方差
SquareAcc //计算方差
}
}
