public void ProcessFrame(UnmanagedImage videoFrame)
{
lock (sync)
{
// check previous frame
if (previousFrame == null)
{
// save image dimension
width = videoFrame.Width;
height = videoFrame.Height;
// alocate memory for previous and current frames
previousFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
motionFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
frameSize = motionFrame.Stride * height;
// temporary buffer
if (suppressNoise)
{
tempFrame = UnmanagedImage.Create(width, height, PixelFormat.Format8bppIndexed);
}
// convert source frame to grayscale
Accord.Vision.Tools.ConvertToGrayscale(videoFrame, previousFrame);
return;
}
// check image dimension
if ((videoFrame.Width != width) || (videoFrame.Height != height))
return;
// convert current image to grayscale
Accord.Vision.Tools.ConvertToGrayscale(videoFrame, motionFrame);
unsafe
{
// pointers to previous and current frames
byte* prevFrame = (byte*)previousFrame.ImageData.ToPointer();
byte* currFrame = (byte*)motionFrame.ImageData.ToPointer();
// difference value
int diff;
// 1 - get difference between frames
// 2 - threshold the difference
// 3 - copy current frame to previous frame
for (int i = 0; i < frameSize; i++, prevFrame++, currFrame++)
{
// difference
diff = (int)*currFrame - (int)*prevFrame;
// copy current frame to previous
*prevFrame = *currFrame;
// 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);
}
// calculate amount of motion pixels
pixelsChanged = 0;
byte* motion = (byte*)motionFrame.ImageData.ToPointer();
for (int i = 0; i < frameSize; i++, motion++)
{
pixelsChanged += (*motion & 1);
}
}
}
}