public void ProcessFrame(UnmanagedImage videoFrame)
{
lock (sync)
{
// check background frame
if (backgroundFrame == null)
{
// save image dimension
width = videoFrame.Width;
height = videoFrame.Height;
// alocate memory for background frame
backgroundFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
frameSize = backgroundFrame.Stride * height;
// convert source frame to grayscale
Accord.Vision.Tools.ConvertToGrayscale(videoFrame, backgroundFrame);
return;
}
// check image dimension
if ((videoFrame.Width != width) || (videoFrame.Height != height))
return;
// check motion frame
if (motionFrame == null)
{
motionFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
// temporary buffer
if (suppressNoise)
{
tempFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
}
}
// convert current image to grayscale
Accord.Vision.Tools.ConvertToGrayscale(videoFrame, motionFrame);
unsafe
{
// pointers to background and current frames
byte* backFrame;
byte* currFrame;
int diff;
backFrame = (byte*)backgroundFrame.ImageData.ToPointer();
currFrame = (byte*)motionFrame.ImageData.ToPointer();
// 1 - get difference between frames
// 2 - threshold the difference
for (int i = 0; i < frameSize; i++, backFrame++, currFrame++)
{
// difference
diff = (int)*currFrame - (int)*backFrame;
// treshold
*currFrame = ((diff >= differenceThreshold) || (diff <= differenceThresholdNeg)) ? (byte)255 : (byte)0;
}
if (suppressNoise)
{
// suppress noise and calculate motion amount
Accord.SystemTools.CopyUnmanagedMemory(tempFrame.ImageData, motionFrame.ImageData, frameSize);
erosionFilter.Apply(tempFrame, motionFrame);
if (keepObjectEdges)
{
Accord.SystemTools.CopyUnmanagedMemory(tempFrame.ImageData, motionFrame.ImageData, frameSize);
dilatationFilter.Apply(tempFrame, motionFrame);
}
}
// calculate amount of motion pixels
pixelsChanged = 0;
byte* motion = (byte*)motionFrame.ImageData.ToPointer();
for (int i = 0; i < frameSize; i++, motion++)
{
pixelsChanged += (*motion & 1);
}
}
}
}