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

ProcessFrame() public method

Process video and motion frames doing further post processing after performed motion detection.

Processes provided motion frame and calculates motion level for each grid's cell. In the case if HighlightMotionGrid property is set to , the cell with motion level above threshold are highlighted.

Motion frame is not 8 bpp image, but it must be so. Video frame must be 8 bpp grayscale image or 24/32 bpp color image.
public ProcessFrame ( UnmanagedImage videoFrame, UnmanagedImage motionFrame ) : void
videoFrame AForge.Imaging.UnmanagedImage Original video frame.
motionFrame AForge.Imaging.UnmanagedImage Motion frame provided by motion detection /// algorithm (see ).
return void
        public unsafe void ProcessFrame( UnmanagedImage videoFrame, UnmanagedImage motionFrame )
        {
            if ( motionFrame.PixelFormat != PixelFormat.Format8bppIndexed )
            {
                throw new InvalidImagePropertiesException( "Motion frame must be 8 bpp image." );
            }

            if ( ( videoFrame.PixelFormat != PixelFormat.Format8bppIndexed ) &&
                 ( videoFrame.PixelFormat != PixelFormat.Format24bppRgb ) &&
                 ( videoFrame.PixelFormat != PixelFormat.Format32bppRgb ) &&
                 ( videoFrame.PixelFormat != PixelFormat.Format32bppArgb ) )
            {
                throw new UnsupportedImageFormatException( "Video frame must be 8 bpp grayscale image or 24/32 bpp color image." );
            } 
            
            int width  = videoFrame.Width;
            int height = videoFrame.Height;
            int pixelSize = Bitmap.GetPixelFormatSize( videoFrame.PixelFormat ) / 8; 

            if ( ( motionFrame.Width != width ) || ( motionFrame.Height != height ) )
                return;

            int cellWidth  = width  / gridWidth;
            int cellHeight = height / gridHeight;

            // temporary variables
            int xCell, yCell;

            // process motion frame calculating amount of changed pixels
            // in each grid's cell
            byte* motion = (byte*) motionFrame.ImageData.ToPointer( );
            int motionOffset = motionFrame.Stride - width;

            for ( int y = 0; y < height; y++ )
            {
                // get current grid's row
                yCell = y / cellHeight;
                // correct row number if image was not divided by grid equally
                if ( yCell >= gridHeight )
                    yCell = gridHeight - 1;

                for ( int x = 0; x < width; x++, motion++ )
                {
                    if ( *motion != 0 )
                    {
                        // get current grid's collumn
                        xCell = x / cellWidth;
                        // correct column number if image was not divided by grid equally
                        if ( xCell >= gridWidth )
                            xCell = gridWidth - 1;

                        motionGrid[yCell, xCell]++;
                    }
                }
                motion += motionOffset;
            }

            // update motion grid converting absolute number of changed
            // pixel to relative for each cell
            int gridHeightM1 = gridHeight - 1;
            int gridWidthM1  = gridWidth  - 1;

            int lastRowHeight   = height - cellHeight * gridHeightM1;
            int lastColumnWidth = width - cellWidth   * gridWidthM1;

            for ( int y = 0; y < gridHeight; y++ )
            {
                int ch = ( y != gridHeightM1 ) ? cellHeight : lastRowHeight;

                for ( int x = 0; x < gridWidth; x++ )
                {
                    int cw = ( x != gridWidthM1 ) ? cellWidth : lastColumnWidth;

                    motionGrid[y, x] /= ( cw * ch );
                }
            }

            if ( highlightMotionGrid )
            {
                // highlight motion grid - cells, which have enough motion

                byte* src = (byte*) videoFrame.ImageData.ToPointer( );
                int srcOffset = videoFrame.Stride - width * pixelSize;

                if ( pixelSize == 1 )
                {
                    // grayscale case
                    byte fillG = (byte) ( 0.2125 * highlightColor.R +
                                          0.7154 * highlightColor.G +
                                          0.0721 * highlightColor.B );

                    for ( int y = 0; y < height; y++ )
                    {
                        yCell = y / cellHeight;
                        if ( yCell >= gridHeight )
                            yCell = gridHeight - 1;

                        for ( int x = 0; x < width; x++, src++ )
                        {
                            xCell = x / cellWidth;
                            if ( xCell >= gridWidth )
                                xCell = gridWidth - 1;

                            if ( ( motionGrid[yCell, xCell] > motionAmountToHighlight ) && ( ( ( x + y ) & 1 ) == 0 ) )
                            {
                                *src = fillG;
                            }
                        }
                        src += srcOffset;
                    }
                }
                else
                {
                    // color case
                    byte fillR = highlightColor.R;
                    byte fillG = highlightColor.G;
                    byte fillB = highlightColor.B;

                    for ( int y = 0; y < height; y++ )
                    {
                        yCell = y / cellHeight;
                        if ( yCell >= gridHeight )
                            yCell = gridHeight - 1;

                        for ( int x = 0; x < width; x++, src += pixelSize )
                        {
                            xCell = x / cellWidth;
                            if ( xCell >= gridWidth )
                                xCell = gridWidth - 1;

                            if ( ( motionGrid[yCell, xCell] > motionAmountToHighlight ) && ( ( ( x + y ) & 1 ) == 0 ) )
                            {
                                src[RGB.R] = fillR;
                                src[RGB.G] = fillG;
                                src[RGB.B] = fillB;
                            }
                        }
                        src += srcOffset;
                    }
                }
            }
        }