public IEnumerable<Bitmap> Apply(Bitmap bitmap) { // assuming scanned background is white we need to invert for the algo to work var copy = new Invert().Apply(bitmap); copy = EnsureGrayscale(copy); new Threshold { ThresholdValue = 25 }.ApplyInPlace(copy); new FillHoles().ApplyInPlace(copy); var blobCounter = new BlobCounter { // set filtering options FilterBlobs = true, MinWidth = 50, MinHeight = 50, }; blobCounter.ProcessImage(copy); var blobs = blobCounter.GetObjectsInformation(); if (blobs.Any()) { var invertedOriginal = new Invert().Apply(bitmap); foreach (var blob in blobs) { // use inverted source to ensure correct edge colors blobCounter.ExtractBlobsImage(invertedOriginal, blob, false); var blobImage = blob.Image.ToManagedImage(); // straighten var angle = new DocumentSkewChecker().GetSkewAngle(EnsureGrayscale(blobImage)); var rotationFilter = new RotateBilinear(-angle) { FillColor = Color.Black }; blobImage = rotationFilter.Apply(blobImage); // crop blobImage = new ExtractBiggestBlob().Apply(blobImage); new Invert().ApplyInPlace(blobImage); yield return blobImage; } } else { yield return bitmap; } }
public List<Blob> ExtractBlob() { // create instance of blob counter BlobCounter blobCounter = new BlobCounter(); // process input image blobCounter.ProcessImage(ImageBitmap); // get information about detected objects Blob[] blobArray = blobCounter.GetObjectsInformation(); foreach(Blob blobdata in blobArray) { blobCounter.ExtractBlobsImage(ImageBitmap, blobdata, true); } return blobArray.ToList(); }
public List<Blob> ExtractBlob(int maxWidth, int maxHeight, int minWidth, int minHeight) { BlobCounter blobCounter = new BlobCounter(); blobCounter.MinHeight = minHeight; blobCounter.MinWidth = minWidth; blobCounter.MaxWidth = maxWidth; blobCounter.MaxHeight = maxHeight; blobCounter.FilterBlobs = true; // process input image blobCounter.ProcessImage(ImageBitmap); // get information about detected objects Blob[] blobArray = blobCounter.GetObjectsInformation(); foreach (Blob blobdata in blobArray) { blobCounter.ExtractBlobsImage(ImageBitmap, blobdata, true); } return blobArray.ToList(); }
public ActionResult Index(string Data, int Smallest = 3, int Largest = 6, HttpPostedFileBase file = null) { string base64Image = null; if (file != null) { //try to determine data from posted file var bitmap = new Bitmap(file.InputStream); // lock image BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // step 1 - turn background to black var filter = new Invert(); filter.ApplyInPlace(bitmapData); ColorFiltering colorFilter = new ColorFiltering(); colorFilter.Red = new IntRange(0, 64); colorFilter.Green = new IntRange(0, 64); colorFilter.Blue = new IntRange(0, 64); colorFilter.FillOutsideRange = false; colorFilter.ApplyInPlace(bitmapData); // step 2 - locating objects BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; blobCounter.MinHeight = 5; blobCounter.MinWidth = 5; blobCounter.ProcessImage(bitmapData); var blobs = blobCounter.GetObjectsInformation(); bitmap.UnlockBits(bitmapData); base64Image = bitmap.ToBase64(); // get information about detected objects var shapeChecker = new SimpleShapeChecker(); var letters = new List<Letter>(); int circleCount = 0; foreach ( var blob in blobs.ToArray() .OrderBy(b => b.Rectangle.Top) .ThenBy(b => b.Rectangle.Left) .ThenByDescending(b => b.Area)) { List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob); AForge.Point center; float radius; if (shapeChecker.IsCircle(edgePoints, out center, out radius)) { //Todo: filter on the largest radius * 90% to deal with resolutions if (radius < 40) continue; blobCounter.ExtractBlobsImage(bitmap, blob, false); var letter = blob.Image.ToManagedImage(true); var resizeFilter = new ResizeBilinear(150, 150); letter = resizeFilter.Apply(letter); var bwBitmap = new Bitmap(75, 75, PixelFormat.Format32bppArgb); for (int y = 40; y < 115; y++) { for (int x = 40; x < 115; x++) { var color = letter.GetPixel(x, y); if (color.Name == "ff000000") { bwBitmap.SetPixel(x - 40, y - 40, Color.Black); } else { bwBitmap.SetPixel(x - 40, y - 40, Color.White); } } } letters.Add(new Letter { L = TrainingData.GetBestGuess(bwBitmap), X = center.X, Y = center.Y, Radius = radius }); } } var minX = letters.Min(c => c.X); var maxX = letters.Max(c => c.X); var minY = letters.Min(c => c.Y); var maxY = letters.Max(c => c.Y); var smallestRadius = letters.Min(c => c.Radius); var numberOfItemsPerRow = (int)((maxX - minX)/ smallestRadius / 2); var numberOfItemsPerCol = (int)((maxY - minY) / smallestRadius / 2); var spaceBetweenPointsX = (maxX - minX)/numberOfItemsPerRow; var spaceBetweenPointsY = (maxY - minY) / numberOfItemsPerCol; var varianceDelta = smallestRadius*.05f; //allow 5% pixel float var puzzle = new StringBuilder(); for (var y = minY; y <= maxY; y += spaceBetweenPointsY) { for (var x = minX; x <= maxX; x += spaceBetweenPointsX) { var item = letters.FirstOrDefault(c => c.X > x - varianceDelta && c.X < x + varianceDelta && c.Y > y - varianceDelta && c.Y < y + varianceDelta); if (item != null) puzzle.Append(item.L); else puzzle.Append("_"); } puzzle.AppendLine(); } Data = puzzle.ToString(); } var solutions = SolvePuzzle(Data, Smallest, Largest); return View(new PuzzleModel { Data = Data, Largest = Largest, Smallest = Smallest, Solutions = solutions, Base64Image = base64Image }); }
public ActionResult Process(HttpPostedFileBase file) { var model = new List<TrainingDataItem>(); var bitmap = new Bitmap(file.InputStream); // lock image BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, PixelFormat.Format24bppRgb); // step 1 - turn background to black var filter = new Invert(); filter.ApplyInPlace(bitmapData); ColorFiltering colorFilter = new ColorFiltering(); colorFilter.Red = new IntRange(0, 64); colorFilter.Green = new IntRange(0, 64); colorFilter.Blue = new IntRange(0, 64); colorFilter.FillOutsideRange = false; colorFilter.ApplyInPlace(bitmapData); // step 2 - locating objects BlobCounter blobCounter = new BlobCounter(); blobCounter.FilterBlobs = true; blobCounter.MinHeight = 5; blobCounter.MinWidth = 5; blobCounter.ProcessImage(bitmapData); var blobs = blobCounter.GetObjectsInformation(); bitmap.UnlockBits(bitmapData); // get information about detected objects var shapeChecker = new SimpleShapeChecker(); int circleCount = 0; foreach ( var blob in blobs.ToArray() .OrderBy(b => b.Rectangle.Top) .ThenBy(b => b.Rectangle.Left) .ThenByDescending(b => b.Area)) { List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blob); AForge.Point center; float radius; if (shapeChecker.IsCircle(edgePoints, out center, out radius)) { //Todo: filter on the largest radius * 90% to deal with resolutions if (radius < 40) continue; blobCounter.ExtractBlobsImage(bitmap, blob, false); var letter = blob.Image.ToManagedImage(true); var resizeFilter = new ResizeBilinear(150, 150); letter = resizeFilter.Apply(letter); var base64 = (letter.ToBase64()); var sb = new StringBuilder(); var bwBitmap = new Bitmap(75, 75, PixelFormat.Format32bppArgb); for (int y = 40; y < 115; y++) { for (int x = 40; x < 115; x++) { var color = letter.GetPixel(x, y); if (color.Name == "ff000000") { sb.Append("0"); bwBitmap.SetPixel(x - 40, y - 40, Color.Black); } else { sb.Append("1"); bwBitmap.SetPixel(x - 40, y - 40, Color.White); } } sb.AppendLine(); } model.Add(new TrainingDataItem { Base64Image = (bwBitmap.ToBase64()), Letter = TrainingData.GetBestGuess(bwBitmap) }); } } return View(model.ToArray()); }