/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// protected override unsafe void ProcessFilter(UnmanagedImage image) { int width = image.Width; int height = image.Height; BlobCounter blobCounter = new BlobCounter(); // 1 - invert the source image Invert invertFilter = new Invert(); using (UnmanagedImage invertedImage = invertFilter.Apply(image)) { // 2 - use blob counter to find holes (they are white objects now on the inverted image) blobCounter.ProcessImage(invertedImage); } Blob[] blobs = blobCounter.GetObjectsInformation(); // 3 - check all blobs and determine which should be filtered byte[] newObjectColors = new byte[blobs.Length + 1]; newObjectColors[0] = 255; // don't touch the objects, which have 0 ID for (int i = 0, n = blobs.Length; i < n; i++) { Blob blob = blobs[i]; if ((blob.Rectangle.Left == 0) || (blob.Rectangle.Top == 0) || (blob.Rectangle.Right == width) || (blob.Rectangle.Bottom == height)) { newObjectColors[blob.ID] = 0; } else { if (((coupledSizeFiltering) && (blob.Rectangle.Width <= maxHoleWidth) && (blob.Rectangle.Height <= maxHoleHeight)) | ((!coupledSizeFiltering) && ((blob.Rectangle.Width <= maxHoleWidth) || (blob.Rectangle.Height <= maxHoleHeight)))) { newObjectColors[blob.ID] = 255; } else { newObjectColors[blob.ID] = 0; } } } // 4 - process the source image image and fill holes byte *ptr = (byte *)image.ImageData.ToPointer(); int offset = image.Stride - width; int[] objectLabels = blobCounter.ObjectLabels; for (int y = 0, i = 0; y < height; y++) { for (int x = 0; x < width; x++, i++, ptr++) { *ptr = newObjectColors[objectLabels[i]]; } ptr += offset; } }
/// <summary> /// Process the filter on the specified image. /// </summary> /// /// <param name="image">Source image data.</param> /// protected override unsafe void ProcessFilter( UnmanagedImage image ) { int width = image.Width; int height = image.Height; // 1 - invert the source image Invert invertFilter = new Invert( ); UnmanagedImage invertedImage = invertFilter.Apply( image ); // 2 - use blob counter to find holes (they are white objects now on the inverted image) BlobCounter blobCounter = new BlobCounter( ); blobCounter.ProcessImage( invertedImage ); Blob[] blobs = blobCounter.GetObjectsInformation( ); // 3 - check all blobs and determine which should be filtered byte[] newObjectColors = new byte[blobs.Length + 1]; newObjectColors[0] = 255; // don't touch the objects, which have 0 ID for ( int i = 0, n = blobs.Length; i < n; i++ ) { Blob blob = blobs[i]; if ( ( blob.Rectangle.Left == 0 ) || ( blob.Rectangle.Top == 0 ) || ( blob.Rectangle.Right == width ) || ( blob.Rectangle.Bottom == height ) ) { newObjectColors[blob.ID] = 0; } else { if ( ( ( coupledSizeFiltering ) && ( blob.Rectangle.Width <= maxHoleWidth ) && ( blob.Rectangle.Height <= maxHoleHeight ) ) | ( ( !coupledSizeFiltering ) && ( ( blob.Rectangle.Width <= maxHoleWidth ) || ( blob.Rectangle.Height <= maxHoleHeight ) ) ) ) { newObjectColors[blob.ID] = 255; } else { newObjectColors[blob.ID] = 0; } } } // 4 - process the source image image and fill holes byte* ptr = (byte*) image.ImageData.ToPointer( ); int offset = image.Stride - width; int[] objectLabels = blobCounter.ObjectLabels; for ( int y = 0, i = 0; y < height; y++ ) { for ( int x = 0; x < width; x++, i++, ptr++ ) { *ptr = newObjectColors[objectLabels[i]]; } ptr += offset; } }
public void GetBlobs2(string inputFile, string outputPath) { UnmanagedImage skewedImg = null; UnmanagedImage bwInvImg = null; { var bmp = new Bitmap(inputFile); var img = UnmanagedImage.FromManagedImage(bmp); var grayImg = Accord.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(img); var bwImg = new Accord.Imaging.Filters.OtsuThreshold().Apply(grayImg); var skewChecker = new DocumentSkewChecker(); double angle = skewChecker.GetSkewAngle(bwImg); var rotateFilter = new Accord.Imaging.Filters.RotateBilinear(-angle); skewedImg = rotateFilter.Apply(img); bwImg.Dispose(); grayImg.Dispose(); img.Dispose(); bmp.Dispose(); } { var grayImg = Accord.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(skewedImg); var bwImg = new Accord.Imaging.Filters.OtsuThreshold().Apply(grayImg); var openingFilter = new Accord.Imaging.Filters.Opening(); openingFilter.ApplyInPlace(bwImg); bwInvImg = new Accord.Imaging.Filters.Invert().Apply(bwImg); bwImg.Dispose(); grayImg.Dispose(); } var blobProc = new Accord.Imaging.BlobCounter(); blobProc.ProcessImage(bwInvImg); var blobs = blobProc.GetObjectsInformation().ToList(); foreach (Accord.Imaging.Blob blob in blobs.OrderBy(b => b.Rectangle.Left).ThenBy(b => b.Rectangle.Top)) { Console.WriteLine("{0} {1}", blob.Rectangle.ToString(), blob.Area.ToString()); } //Layout parameters var expectedLineMarkerSize = new System.Drawing.Size(25, 10); //new System.Drawing.Size(35, 15); var expectedCellSize = new System.Drawing.Size(15, 10); //new System.Drawing.Size(20, 13); int expectedNumlineMarkers = 19; // 23; int tolerance = 3; //Limits to determine in a cell is marked double fullnessOk = .75; double fullnessUnsure = .65; var questions = new List <Tuple <int, Accord.Imaging.Blob, List <Accord.Imaging.Blob> > >(); { var lineMarkers = blobs.Where(b => { if (b.Rectangle.Width < expectedLineMarkerSize.Width - tolerance) { return(false); } if (b.Rectangle.Width > expectedLineMarkerSize.Width + tolerance) { return(false); } if (b.Rectangle.Height < expectedLineMarkerSize.Height - tolerance) { return(false); } if (b.Rectangle.Height > expectedLineMarkerSize.Height + tolerance) { return(false); } return(true); }) .OrderBy(b => b.Rectangle.Left) .ThenBy(b => b.Rectangle.Top) .ToList(); if (lineMarkers.Count() != expectedNumlineMarkers) { throw new Exception(string.Format("Can't locate all line markers. Expected {0}, found {1}", expectedNumlineMarkers, lineMarkers.Count)); } var cells = blobs.Where(b => { if (b.Rectangle.Width < expectedCellSize.Width - tolerance) { return(false); } if (b.Rectangle.Width > expectedCellSize.Width + tolerance) { return(false); } if (b.Rectangle.Height < expectedCellSize.Height - tolerance) { return(false); } if (b.Rectangle.Height > expectedCellSize.Height + tolerance) { return(false); } return(true); }).ToList(); int idxLine = 1; foreach (var lineMarker in lineMarkers.OrderBy(b => b.CenterOfGravity.Y)) { var cellsOfLine = cells.Where(b => Math.Abs(b.CenterOfGravity.Y - lineMarker.CenterOfGravity.Y) <= tolerance) .Take(5) .ToList() .OrderBy(b => b.CenterOfGravity.X) .ToList(); questions.Add(new Tuple <int, Accord.Imaging.Blob, List <Accord.Imaging.Blob> >(idxLine, lineMarker, cellsOfLine)); idxLine++; } } { var bmp = skewedImg.ToManagedImage(); using (Graphics g = Graphics.FromImage(bmp)) { foreach (var question in questions) { g.FillRectangle(new SolidBrush(Color.Blue), question.Item2.Rectangle); g.DrawString(question.Item1.ToString(), new System.Drawing.Font("Arial", 8), new SolidBrush(Color.White), question.Item2.Rectangle); int column = 1; foreach (Accord.Imaging.Blob blob in question.Item3.OrderBy(b => b.Rectangle.Left).ThenBy(b => b.Rectangle.Top)) { if (System.Diagnostics.Debugger.IsAttached) { Console.WriteLine("Line {0}, Column {1}, Fullness {2}", question.Item1, column, Math.Round(blob.Fullness, 2)); } if (blob.Fullness >= fullnessOk) { g.DrawRectangle(new Pen(Color.Green, 2), blob.Rectangle); } else if (blob.Fullness >= fullnessUnsure) { g.DrawRectangle(new Pen(Color.Yellow, 2), blob.Rectangle); } else { g.DrawRectangle(new Pen(Color.Red, 2), blob.Rectangle); } column++; } } } // bmp.Save(outp); } }
private void SetFilter() { ImageType = ImageTypes.Rgb24bpp; Af.Invert newFilter = new Af.Invert(); imageFilter = newFilter; }
private void videoSourcePlayer1_NewFrame(object sender, ref Bitmap image) { Invert inv = new Invert(); inv.ApplyInPlace(image); UnmanagedImage ui = UnmanagedImage.FromManagedImage(image); pictureBox1.Image = image; if (controller.Tracker.TrackingObject == null) return; if (controller.Tracker.TrackingObject.IsEmpty) return; var rect = controller.Tracker.TrackingObject.Rectangle; Crop crop = new Crop(rect); UnmanagedImage head = crop.Apply(ui); var points = new List<IntPoint>() { new IntPoint(head.Width / 2, head.Height / 2) }; var pps = head.Collect16bppPixelValues(points); double mean = pps.Mean(); double cutoff = mean + 15; Threshold t = new Threshold((int)cutoff); var mask = t.Apply(ui); LevelsLinear16bpp levels = new LevelsLinear16bpp(); levels.InGray = new IntRange((int)cutoff, 65535); levels.OutGray = new IntRange(0, 65535); levels.ApplyInPlace(ui); var mask8bit = Accord.Imaging.Image.Convert16bppTo8bpp(mask.ToManagedImage()); BlobCounter bc = new BlobCounter(); bc.ObjectsOrder = ObjectsOrder.Area; bc.ProcessImage(mask8bit); var blobs = bc.GetObjectsInformation(); inv.ApplyInPlace(image); Intersect intersect = new Intersect(); intersect.UnmanagedOverlayImage = mask; mask = intersect.Apply(ui); List<Rectangle> rects = new List<Rectangle>(); // Extract the uppermost largest blobs. for (int i = 0; i < blobs.Length; i++) { double dx = (blobs[i].Rectangle.Top - controller.Tracker.TrackingObject.Center.Y); double d = (dx * dx) / controller.Tracker.TrackingObject.Area; if (d < 2 && blobs[i].Area > 1000) rects.Add(blobs[i].Rectangle); } rects.Sort(compare); if (rects.Count > 0) { captureHand(mask, rects[0], pbLeftArm, pbLeftHand); } if (rects.Count > 1) { captureHand(mask, rects[1], pbRightArm, pbRightHand); } RectanglesMarker marker = new RectanglesMarker(rects); marker.MarkerColor = Color.White; marker.ApplyInPlace(mask8bit); image = mask.ToManagedImage(); }