Accord.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 Accord.Imaging.UnmanagedImage Video frame to process (detect motion in).
return void
        public 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
                    Accord.Vision.Tools.ConvertToGrayscale(videoFrame, backgroundFrame);

                    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 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
                        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 );
                    }
                }
            }
        }