// 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); //get image byte[] textData = GetImageData(); UnmanagedImage img = CreateImage(textData); log.AddImage("Raw Image", img.ToManagedImage()); //resize Image AForge.Imaging.Filters.ResizeNearestNeighbor resizeFilter = new AForge.Imaging.Filters.ResizeNearestNeighbor(500, (int)(500 / res)); UnmanagedImage resizedImage = resizeFilter.Apply(img); log.AddImage("Resized Image", resizedImage.ToManagedImage()); //filter floor UnmanagedImage floorFilteredImage = FilterFloor(resizedImage, textData); log.AddImage("Floor filtered", floorFilteredImage.ToManagedImage()); // 1- grayscale image Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply(resizedImage.ToManagedImage()); log.AddImage("Grayscale", resizedImage.ToManagedImage()); // 2 - Otsu thresholding OtsuThreshold threshold = new OtsuThreshold(); Bitmap binaryImage = threshold.Apply(grayImage); log.AddImage("Binary", binaryImage); log.AddMessage("Otsu threshold: " + threshold.ThresholdValue); //resive image // 3 - Blob counting BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; blobCounter.MinWidth = 1; blobCounter.MinWidth = 1; blobCounter.ProcessImage(binaryImage); Blob[] blobs = blobCounter.GetObjectsInformation(); log.AddMessage("Found blobs (min width/height = 24): " + blobs.Length); }
// 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 image Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply(image); log.AddImage("Grayscale", grayImage); // 2 - Otsu thresholding OtsuThreshold threshold = new OtsuThreshold( ); Bitmap binaryImage = threshold.Apply(grayImage); log.AddImage("Binary", binaryImage); log.AddMessage("Otsu threshold: " + threshold.ThresholdValue); // 3 - Blob counting BlobCounter blobCounter = new BlobCounter( ); blobCounter.FilterBlobs = true; blobCounter.MinWidth = 24; blobCounter.MinWidth = 24; blobCounter.ProcessImage(binaryImage); Blob[] blobs = blobCounter.GetObjectsInformation( ); log.AddMessage("Found blobs (min width/height = 24): " + blobs.Length); // 4 - check shape of each blob SimpleShapeChecker shapeChecker = new SimpleShapeChecker( ); log.AddMessage("Found coins: "); int count = 0; // create graphics object for drawing on image Graphics g = Graphics.FromImage(image); Pen pen = new Pen(Color.Red, 3); foreach (Blob blob in blobs) { List <IntPoint> edgePoint = blobCounter.GetBlobsEdgePoints(blob); // check if shape looks like a circle AForge.Point center; float radius; if (shapeChecker.IsCircle(edgePoint, out center, out radius)) { count++; log.AddMessage(string.Format(" {0}: center = ({1}, {2}), radius = {3}", count, center.X, center.Y, radius)); // highlight coin g.DrawEllipse(pen, (int)(center.X - radius), (int)(center.Y - radius), (int)(radius * 2), (int)(radius * 2)); } } g.Dispose( ); pen.Dispose( ); log.AddMessage("Total coins: " + count); log.AddImage("Coins", image); }
// 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 unmanaged copy of source image, so we could draw on it UnmanagedImage imageData = UnmanagedImage.FromManagedImage(image); // Get unmanaged copy of grayscale image, so we could access it's pixel values UnmanagedImage grayUI = UnmanagedImage.FromManagedImage(grayImage); // 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 = this.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.FromArgb(255, 255, 0, 0)); // add the object to the list of interesting objects for further processing foundObjects.Add(corners); } } } } log.AddImage("Potential glyps", imageData.ToManagedImage()); 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(ref 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++; } }
// 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++; } }
// 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 image Bitmap grayImage = Grayscale.CommonAlgorithms.BT709.Apply( image ); log.AddImage( "Grayscale", grayImage ); // 2 - Otsu thresholding OtsuThreshold threshold = new OtsuThreshold( ); Bitmap binaryImage = threshold.Apply( grayImage ); log.AddImage( "Binary", binaryImage ); log.AddMessage( "Otsu threshold: " + threshold.ThresholdValue ); // 3 - Blob counting BlobCounter blobCounter = new BlobCounter( ); blobCounter.FilterBlobs = true; blobCounter.MinWidth = 24; blobCounter.MinWidth = 24; blobCounter.ProcessImage( binaryImage ); Blob[] blobs = blobCounter.GetObjectsInformation( ); log.AddMessage( "Found blobs (min width/height = 24): " + blobs.Length ); // 4 - check shape of each blob SimpleShapeChecker shapeChecker = new SimpleShapeChecker( ); log.AddMessage( "Found coins: " ); int count = 0; // create graphics object for drawing on image Graphics g = Graphics.FromImage( image ); Pen pen = new Pen( Color.Red, 3 ); foreach ( Blob blob in blobs ) { List<IntPoint> edgePoint = blobCounter.GetBlobsEdgePoints( blob ); // check if shape looks like a circle DoublePoint center; double radius; if ( shapeChecker.IsCircle( edgePoint, out center, out radius ) ) { count++; log.AddMessage( string.Format( " {0}: center = ({1}, {2}), radius = {3}", count, center.X, center.Y, radius ) ); // highlight coin g.DrawEllipse( pen, (int) ( center.X - radius ), (int) ( center.Y - radius ), (int) ( radius * 2 ), (int) ( radius * 2 ) ); } } g.Dispose( ); pen.Dispose( ); log.AddMessage( "Total coins: " + count); log.AddImage( "Coins", image ); }