Exemplo n.º 1
0
        // Process specified image trying to recognize counter's image
        public void Process(Bitmap image, IImageProcessingLog log)
        {
            log.AddMessage("Image size: " + image.Width + " x " + image.Height);

            // 1 - Grayscale
            Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image);

            log.AddImage("Grayscale", grayImage);

            // 2 - Edge detection
            DifferenceEdgeDetector edgeDetector = new DifferenceEdgeDetector( );
            Bitmap edges = edgeDetector.Apply(grayImage);

            log.AddImage("Edges", edges);

            // 3 - Threshold edges
            Threshold thresholdFilter = new Threshold(40);

            thresholdFilter.ApplyInPlace(edges);
            log.AddImage("Thresholded Edges", edges);

            // 4 - Blob Counter
            BlobCounter blobCounter = new BlobCounter( );

            blobCounter.MinHeight    = 32;
            blobCounter.MinWidth     = 32;
            blobCounter.FilterBlobs  = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            blobCounter.ProcessImage(edges);
            Blob[] blobs = blobCounter.GetObjectsInformation( );

            // create copy of source image, so we could draw on it
            Bitmap imageCopy = AForge.Imaging.Image.Clone(image);

            BitmapData imageData = imageCopy.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                                                      ImageLockMode.ReadWrite, imageCopy.PixelFormat);

            // lock grayscale image, so we could access it's pixel values
            BitmapData grayData = grayImage.LockBits(new Rectangle(0, 0, image.Width, image.Height),
                                                     ImageLockMode.ReadOnly, grayImage.PixelFormat);
            UnmanagedImage grayUI = new UnmanagedImage(grayData);

            // list of found dark/black quadrilaterals surrounded by white area
            List <List <IntPoint> > foundObjects = new List <List <IntPoint> >( );
            // shape checker for checking quadrilaterals
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker( );

            // 5 - check each blob
            for (int i = 0, n = blobs.Length; i < n; i++)
            {
                List <IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]);
                List <IntPoint> corners    = null;

                // does it look like a quadrilateral ?
                if (shapeChecker.IsQuadrilateral(edgePoints, out corners))
                {
                    // do some more checks to filter so unacceptable shapes
                    // if ( CheckIfShapeIsAcceptable( corners ) )
                    {
                        log.AddMessage("Blob size: " + blobs[i].Rectangle.Width + " x " + blobs[i].Rectangle.Height);

                        // get edge points on the left and on the right side
                        List <IntPoint> leftEdgePoints, rightEdgePoints;
                        blobCounter.GetBlobsLeftAndRightEdges(blobs[i], out leftEdgePoints, out rightEdgePoints);

                        // calculate average difference between pixel values from outside of the shape and from inside
                        float diff = CalculateAverageEdgesBrightnessDifference(
                            leftEdgePoints, rightEdgePoints, grayUI);

                        log.AddMessage("Avg Diff: " + diff);

                        // check average difference, which tells how much outside is lighter than inside on the average
                        if (diff > 20)
                        {
                            Drawing.Polygon(imageData, corners, Color.Red);
                            // add the object to the list of interesting objects for further processing
                            foundObjects.Add(corners);
                        }
                    }
                }
            }

            imageCopy.UnlockBits(imageData);
            grayImage.UnlockBits(grayData);

            log.AddImage("Potential glyps", imageCopy);

            int counter = 1;

            // further processing of each potential glyph
            foreach (List <IntPoint> corners in foundObjects)
            {
                log.AddMessage("Glyph #" + counter);

                log.AddMessage(string.Format("Corners: ({0}), ({1}), ({2}), ({3})",
                                             corners[0], corners[1], corners[2], corners[3]));

                // 6 - do quadrilateral transformation
                QuadrilateralTransformation quadrilateralTransformation =
                    new QuadrilateralTransformation(corners, 250, 250);

                Bitmap transformed = quadrilateralTransformation.Apply(grayImage);

                log.AddImage("Transformed #" + counter, transformed);

                // 7 - otsu thresholding
                OtsuThreshold otsuThresholdFilter = new OtsuThreshold( );
                Bitmap        transformedOtsu     = otsuThresholdFilter.Apply(transformed);
                log.AddImage("Transformed Otsu #" + counter, transformedOtsu);

                int glyphSize = 5;
                SquareBinaryGlyphRecognizer gr = new SquareBinaryGlyphRecognizer(glyphSize);

                bool[,] glyphValues = gr.Recognize(transformedOtsu,
                                                   new Rectangle(0, 0, 250, 250));

                log.AddImage("Glyph lines #" + counter, transformedOtsu);

                // output recognize glyph to log
                log.AddMessage(string.Format("glyph: {0:F2}%", gr.confidence * 100));
                for (int i = 0; i < glyphSize; i++)
                {
                    StringBuilder sb = new StringBuilder("   ");

                    for (int j = 0; j < glyphSize; j++)
                    {
                        sb.Append((glyphValues[i, j]) ? "1 " : "0 ");
                    }

                    log.AddMessage(sb.ToString( ));
                }

                counter++;
            }
        }
Exemplo n.º 2
0
        // Process specified image trying to recognize counter's image
        public void Process( Bitmap image, IImageProcessingLog log )
        {
            log.AddMessage( "Image size: " + image.Width + " x " + image.Height );

            // 1 - Grayscale
            Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply( image );
            log.AddImage( "Grayscale", grayImage );

            // 2 - Edge detection
            DifferenceEdgeDetector edgeDetector = new DifferenceEdgeDetector( ); 
            Bitmap edges = edgeDetector.Apply( grayImage );
            log.AddImage( "Edges", edges );

            // 3 - Threshold edges
            Threshold thresholdFilter = new Threshold( 40 ); 
            thresholdFilter.ApplyInPlace( edges );
            log.AddImage( "Thresholded Edges", edges );

            // 4 - Blob Counter
            BlobCounter blobCounter = new BlobCounter( );
            blobCounter.MinHeight = 32;
            blobCounter.MinWidth  = 32;
            blobCounter.FilterBlobs  = true;
            blobCounter.ObjectsOrder = ObjectsOrder.Size;

            blobCounter.ProcessImage( edges );
            Blob[] blobs = blobCounter.GetObjectsInformation( );

            // create copy of source image, so we could draw on it
            Bitmap imageCopy = AForge.Imaging.Image.Clone( image );

            BitmapData imageData = imageCopy.LockBits( new Rectangle( 0, 0, image.Width, image.Height ),
                ImageLockMode.ReadWrite, imageCopy.PixelFormat );

            // lock grayscale image, so we could access it's pixel values
            BitmapData grayData = grayImage.LockBits( new Rectangle( 0, 0, image.Width, image.Height ),
                ImageLockMode.ReadOnly, grayImage.PixelFormat );
            UnmanagedImage grayUI = new UnmanagedImage( grayData );

            // list of found dark/black quadrilaterals surrounded by white area
            List<List<IntPoint>> foundObjects = new List<List<IntPoint>>( );
            // shape checker for checking quadrilaterals
            SimpleShapeChecker shapeChecker = new SimpleShapeChecker( );

            // 5 - check each blob
            for ( int i = 0, n = blobs.Length; i < n; i++ )
            {
                List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints( blobs[i] );
                List<IntPoint> corners = null;

                // does it look like a quadrilateral ?
                if ( shapeChecker.IsQuadrilateral( edgePoints, out corners ) )
                {
                    // do some more checks to filter so unacceptable shapes
                    // if ( CheckIfShapeIsAcceptable( corners ) )
                    {
                        log.AddMessage( "Blob size: " + blobs[i].Rectangle.Width + " x " + blobs[i].Rectangle.Height );

                        // get edge points on the left and on the right side
                        List<IntPoint> leftEdgePoints, rightEdgePoints;
                        blobCounter.GetBlobsLeftAndRightEdges( blobs[i], out leftEdgePoints, out rightEdgePoints );

                        // calculate average difference between pixel values from outside of the shape and from inside
                        float diff = CalculateAverageEdgesBrightnessDifference(
                            leftEdgePoints, rightEdgePoints, grayUI );

                        log.AddMessage( "Avg Diff: " + diff );

                        // check average difference, which tells how much outside is lighter than inside on the average
                        if ( diff > 20 )
                        {
                            Drawing.Polygon( imageData, corners, Color.Red );
                            // add the object to the list of interesting objects for further processing
                            foundObjects.Add( corners );
                        }
                    }
                }
            }

            imageCopy.UnlockBits( imageData );
            grayImage.UnlockBits( grayData );

            log.AddImage( "Potential glyps", imageCopy );

            int counter = 1;

            // further processing of each potential glyph
            foreach ( List<IntPoint> corners in foundObjects )
            {
                log.AddMessage( "Glyph #" + counter );
                
                log.AddMessage( string.Format( "Corners: ({0}), ({1}), ({2}), ({3})",
                    corners[0], corners[1], corners[2], corners[3] ) );

                // 6 - do quadrilateral transformation
                QuadrilateralTransformation quadrilateralTransformation =
                    new QuadrilateralTransformation( corners, 250, 250 );

                Bitmap transformed = quadrilateralTransformation.Apply( grayImage );

                log.AddImage( "Transformed #" + counter, transformed );

                // 7 - otsu thresholding
                OtsuThreshold otsuThresholdFilter = new OtsuThreshold( ); 
                Bitmap transformedOtsu = otsuThresholdFilter.Apply( transformed );
                log.AddImage( "Transformed Otsu #" + counter, transformedOtsu );

                int glyphSize = 5;
                SquareBinaryGlyphRecognizer gr = new SquareBinaryGlyphRecognizer( glyphSize );

                bool[,] glyphValues = gr.Recognize( transformedOtsu,
                    new Rectangle( 0, 0, 250, 250 ) );

                log.AddImage( "Glyph lines #" + counter, transformedOtsu );

                // output recognize glyph to log
                log.AddMessage( string.Format( "glyph: {0:F2}%", gr.confidence * 100 ) );
                for ( int i = 0; i < glyphSize; i++ )
                {
                    StringBuilder sb = new StringBuilder( "   " );

                    for ( int j = 0; j < glyphSize; j++ )
                    {
                        sb.Append( ( glyphValues[i, j] ) ? "1 " : "0 " );
                    }

                    log.AddMessage( sb.ToString( ) );
                }

                counter++;
            }
        }