AForge.Imaging.ExhaustiveTemplateMatching.ProcessImage C# (CSharp) Method

ProcessImage() public method

Process image looking for matchings with specified template.
The source image has incorrect pixel format. Template image is bigger than search zone.
public ProcessImage ( UnmanagedImage image, UnmanagedImage template, Rectangle searchZone ) : AForge.Imaging.TemplateMatch[]
image UnmanagedImage Unmanaged source image to process.
template UnmanagedImage Unmanaged template image to search for.
searchZone System.Drawing.Rectangle Rectangle in source image to search template for.
return AForge.Imaging.TemplateMatch[]
        public TemplateMatch[] ProcessImage( UnmanagedImage image, UnmanagedImage template, Rectangle searchZone )
        {
            // check image format
            if (
                ( ( image.PixelFormat != PixelFormat.Format8bppIndexed ) &&
                  ( image.PixelFormat != PixelFormat.Format24bppRgb ) ) ||
                ( image.PixelFormat != template.PixelFormat ) )
            {
                throw new UnsupportedImageFormatException( "Unsupported pixel format of the source or template image." );
            }

            // clip search zone
            Rectangle zone = searchZone;
            zone.Intersect( new Rectangle( 0, 0, image.Width, image.Height ) );

            // search zone's starting point
            int startX = zone.X;
            int startY = zone.Y;

            // get source and template image size
            int sourceWidth    = zone.Width;
            int sourceHeight   = zone.Height;
            int templateWidth  = template.Width;
            int templateHeight = template.Height;

            // check template's size
            if ( ( templateWidth > sourceWidth ) || ( templateHeight > sourceHeight ) )
            {
                throw new InvalidImagePropertiesException( "Template's size should be smaller or equal to search zone." );
            }

            int pixelSize = ( image.PixelFormat == PixelFormat.Format8bppIndexed ) ? 1 : 3;
            int sourceStride = image.Stride;

            // similarity map. its size is increased by 4 from each side to increase
            // performance of non-maximum suppresion
            int mapWidth  = sourceWidth - templateWidth + 1;
            int mapHeight = sourceHeight - templateHeight + 1;
            int[,] map = new int[mapHeight + 4, mapWidth + 4];

            // maximum possible difference with template
            int maxDiff = templateWidth * templateHeight * pixelSize * 255;

            // integer similarity threshold
            int threshold = (int) ( similarityThreshold * maxDiff );

            // width of template in bytes
            int templateWidthInBytes = templateWidth * pixelSize;

            // do the job
            unsafe
            {
                byte* baseSrc = (byte*) image.ImageData.ToPointer( );
                byte* baseTpl = (byte*) template.ImageData.ToPointer( );

                int sourceOffset = image.Stride - templateWidth * pixelSize;
                int templateOffset = template.Stride - templateWidth * pixelSize;

                // for each row of the source image
                for ( int y = 0; y < mapHeight; y++ )
                {
                    // for each pixel of the source image
                    for ( int x = 0; x < mapWidth; x++ )
                    {
                        byte* src = baseSrc + sourceStride * ( y + startY ) + pixelSize * ( x + startX );
                        byte* tpl = baseTpl;

                        // compare template with source image starting from current X,Y
                        int dif = 0;

                        // for each row of the template
                        for ( int i = 0; i < templateHeight; i++ )
                        {
                            // for each pixel of the template
                            for ( int j = 0; j < templateWidthInBytes; j++, src++, tpl++ )
                            {
                                int d = *src - *tpl;
                                if ( d > 0 )
                                {
                                    dif += d;
                                }
                                else
                                {
                                    dif -= d;
                                }
                            }
                            src += sourceOffset;
                            tpl += templateOffset;
                        }

                        // templates similarity
                        int sim = maxDiff - dif;

                        if ( sim >= threshold )
                            map[y + 2, x + 2] = sim;
                    }
                }
            }

            // collect interesting points - only those points, which are local maximums
            List<TemplateMatch> matchingsList = new List<TemplateMatch>( );

            // for each row
            for ( int y = 2, maxY = mapHeight + 2; y < maxY; y++ )
            {
                // for each pixel
                for ( int x = 2, maxX = mapWidth + 2; x < maxX; x++ )
                {
                    int currentValue = map[y, x];

                    // for each windows' row
                    for ( int i = -2; ( currentValue != 0 ) && ( i <= 2 ); i++ )
                    {
                        // for each windows' pixel
                        for ( int j = -2; j <= 2; j++ )
                        {
                            if ( map[y + i, x + j] > currentValue )
                            {
                                currentValue = 0;
                                break;
                            }
                        }
                    }

                    // check if this point is really interesting
                    if ( currentValue != 0 )
                    {
                        matchingsList.Add( new TemplateMatch(
                            new Rectangle( x - 2 + startX, y - 2 + startY, templateWidth, templateHeight ),
                            (float) currentValue / maxDiff ) );
                    }
                }
            }

            // convert list to array
            TemplateMatch[] matchings = new TemplateMatch[matchingsList.Count];
            matchingsList.CopyTo( matchings );
            // sort in descending order
            Array.Sort( matchings, new MatchingsSorter( ) );

            return matchings;
        }

Same methods

ExhaustiveTemplateMatching::ProcessImage ( Bitmap image, Bitmap template ) : AForge.Imaging.TemplateMatch[]
ExhaustiveTemplateMatching::ProcessImage ( Bitmap image, Bitmap template, Rectangle searchZone ) : AForge.Imaging.TemplateMatch[]
ExhaustiveTemplateMatching::ProcessImage ( BitmapData imageData, BitmapData templateData ) : AForge.Imaging.TemplateMatch[]
ExhaustiveTemplateMatching::ProcessImage ( BitmapData imageData, BitmapData templateData, Rectangle searchZone ) : AForge.Imaging.TemplateMatch[]
ExhaustiveTemplateMatching::ProcessImage ( UnmanagedImage image, UnmanagedImage template ) : AForge.Imaging.TemplateMatch[]

Usage Example

        /// <summary>
        /// Scans rank of face cards
        /// </summary>
        /// <param name="cardImage"></param>
        /// <returns></returns>
        private Rank ScanFaceRank(Bitmap bmp)
        {
            //Initiliaze template matching class with 0.75 threshold
            ExhaustiveTemplateMatching templateMatchin = new ExhaustiveTemplateMatching(0.75f);
            Rank rank = Rank.NOT_RECOGNIZED;

            if (templateMatchin.ProcessImage(bmp, j).Length > 0) //If Jack template matches
                rank = Rank.Jack;
            if (templateMatchin.ProcessImage(bmp, k).Length > 0)//If King template matches
                rank = Rank.King;
            if (templateMatchin.ProcessImage(bmp, q).Length > 0)//If Queen template matches
                rank = Rank.Queen;

            return rank;
        }
All Usage Examples Of AForge.Imaging.ExhaustiveTemplateMatching::ProcessImage