AForge.Vision.Motion.SimpleBackgroundModelingDetector.ProcessFrame C# (CSharp) Method

ProcessFrame() public method

Process new video frame.

Processes new frame from video source and detects motion in it.

Check MotionLevel property to get information about amount of motion (changes) in the processed frame.

public ProcessFrame ( UnmanagedImage videoFrame ) : void
videoFrame AForge.Imaging.UnmanagedImage Video frame to process (detect motion in).
return void
        public unsafe void ProcessFrame( UnmanagedImage videoFrame )
        {
            lock ( sync )
            {
                // check background frame
                if ( backgroundFrame == null )
                {
                    lastTimeMeasurment = DateTime.Now;

                    // save image dimension
                    width  = videoFrame.Width;
                    height = videoFrame.Height;

                    // alocate memory for previous and current frames
                    backgroundFrame = 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
                    Tools.ConvertToGrayscale( videoFrame, backgroundFrame );

                    return;
                }

                // check image dimension
                if ( ( videoFrame.Width != width ) || ( videoFrame.Height != height ) )
                    return;

                // convert current image to grayscale
                Tools.ConvertToGrayscale( videoFrame, motionFrame );

                // pointers to background and current frames
                byte* backFrame;
                byte* currFrame;
                int diff;

                // update background frame
                if ( millisecondsPerBackgroundUpdate == 0 )
                {
                    // update background frame using frame counter as a base
                    if ( ++framesCounter == framesPerBackgroundUpdate )
                    {
                        framesCounter = 0;

                        backFrame = (byte*) backgroundFrame.ImageData.ToPointer( );
                        currFrame = (byte*) motionFrame.ImageData.ToPointer( );

                        for ( int i = 0; i < frameSize; i++, backFrame++, currFrame++ )
                        {
                            diff = *currFrame - *backFrame;
                            if ( diff > 0 )
                            {
                                ( *backFrame )++;
                            }
                            else if ( diff < 0 )
                            {
                                ( *backFrame )--;
                            }
                        }
                    }
                }
                else
                {
                    // update background frame using timer as a base

                    // get current time and calculate difference
                    DateTime currentTime = DateTime.Now;
                    TimeSpan timeDff = currentTime - lastTimeMeasurment;
                    // save current time as the last measurment
                    lastTimeMeasurment = currentTime;

                    int millisonds = (int) timeDff.TotalMilliseconds + millisecondsLeftUnprocessed;

                    // save remainder so it could be taken into account in the future
                    millisecondsLeftUnprocessed = millisonds % millisecondsPerBackgroundUpdate;
                    // get amount for background update 
                    int updateAmount = (int) ( millisonds / millisecondsPerBackgroundUpdate );

                    backFrame = (byte*) backgroundFrame.ImageData.ToPointer( );
                    currFrame = (byte*) motionFrame.ImageData.ToPointer( );

                    for ( int i = 0; i < frameSize; i++, backFrame++, currFrame++ )
                    {
                        diff = *currFrame - *backFrame;
                        if ( diff > 0 )
                        {
                            ( *backFrame ) += (byte) ( (  diff < updateAmount ) ? diff :  updateAmount );
                        }
                        else if ( diff < 0 )
                        {
                            ( *backFrame ) += (byte) ( ( -diff < updateAmount ) ? diff : -updateAmount );
                        }
                    }
                }

                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
                    AForge.SystemTools.CopyUnmanagedMemory( tempFrame.ImageData, motionFrame.ImageData, frameSize );
                    erosionFilter.Apply( tempFrame, motionFrame );

                    if ( keepObjectEdges )
                    {
                        AForge.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 );
                }
            }
        }