public void FindContourTest2() { Bitmap bmp = Accord.Imaging.Image.Clone(Properties.Resources.hand2); BlobCounter bc = new BlobCounter(bmp); bc.ObjectsOrder = ObjectsOrder.Size; Blob[] blobs = bc.GetObjectsInformation(); bc.ExtractBlobsImage(bmp, blobs[0], true); List<IntPoint> expected = bc.GetBlobsEdgePoints(blobs[0]); Bitmap blob = blobs[0].Image.ToManagedImage(); BorderFollowing bf = new BorderFollowing(); List<IntPoint> actual = bf.FindContour(blob); foreach (IntPoint point in expected) Assert.IsTrue(actual.Contains(point)); IntPoint prev = actual[0]; for (int i = 1; i < actual.Count; i++) { IntPoint curr = actual[i]; Assert.IsTrue(System.Math.Abs(prev.X - curr.X) <= 1 && System.Math.Abs(prev.Y - curr.Y) <= 1); prev = curr; } IntPoint first = actual[0]; IntPoint last = actual[actual.Count - 1]; Assert.IsTrue(System.Math.Abs(first.X - last.X) <= 1 && System.Math.Abs(first.Y - last.Y) <= 1); }
public void FindDefectsTest() { Bitmap bmp = Accord.Imaging.Image.Clone(Properties.Resources.hand); Bitmap gray = Accord.Imaging.Filters.Grayscale.CommonAlgorithms.BT709.Apply(bmp); BlobCounter bc = new BlobCounter(gray); bc.ObjectsOrder = ObjectsOrder.Size; Blob[] blobs = bc.GetObjectsInformation(); bc.ExtractBlobsImage(bmp, blobs[0], true); Bitmap blob = blobs[0].Image.ToManagedImage(); BorderFollowing bf = new BorderFollowing(); List<IntPoint> contour = bf.FindContour(blob); GrahamConvexHull graham = new GrahamConvexHull(); List<IntPoint> hull = graham.FindHull(contour); ConvexHullDefects hullDefects = new ConvexHullDefects(10); List<ConvexityDefect> defects = hullDefects.FindDefects(contour, hull); /* PointsMarker marker = new PointsMarker(hull, Color.Green, 10); marker.ApplyInPlace(blob); ImageBox.Show(blob); */ Assert.AreEqual(2, defects.Count); Assert.AreEqual(new IntPoint(130, 10), contour[defects[0].Start]); Assert.AreEqual(new IntPoint(93, 109), contour[defects[0].Point]); Assert.AreEqual(new IntPoint(64, 9), contour[defects[0].End]); Assert.AreEqual(99.549179077148438, defects[0].Depth, 1e-5); Assert.IsFalse(double.IsNaN(defects[0].Depth)); // Assert.AreEqual(9912.9531239366424, defects[0].Area); Assert.AreEqual(new IntPoint(49, 18), contour[defects[1].Start]); Assert.AreEqual(new IntPoint(61, 106), contour[defects[1].Point]); Assert.AreEqual(new IntPoint(18, 127), contour[defects[1].End]); Assert.AreEqual(35.615153852366504, defects[1].Depth, 1e-5); Assert.IsFalse(double.IsNaN(defects[1].Depth)); // Assert.AreEqual(2293.7535682510002, defects[1].Area); }
// Process image private void ProcessImage(Bitmap bitmap) { // lock image BitmapData bitmapData = bitmap.LockBits( new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); // step 1 - turn background to black 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); Blob[] blobs = blobCounter.GetObjectsInformation(); bitmap.UnlockBits(bitmapData); // step 3 - check objects' type and highlight SimpleShapeChecker shapeChecker = new SimpleShapeChecker(); Graphics g = Graphics.FromImage(bitmap); Pen yellowPen = new Pen(Color.Yellow, 2); // circles Pen redPen = new Pen(Color.Red, 2); // quadrilateral Pen brownPen = new Pen(Color.Brown, 2); // quadrilateral with known sub-type Pen greenPen = new Pen(Color.Green, 2); // known triangle Pen bluePen = new Pen(Color.Blue, 2); // triangle for (int i = 0, n = blobs.Length; i < n; i++) { List<IntPoint> edgePoints = blobCounter.GetBlobsEdgePoints(blobs[i]); Accord.Point center; float radius; // is circle ? if (shapeChecker.IsCircle(edgePoints, out center, out radius)) { g.DrawEllipse(yellowPen, (float)(center.X - radius), (float)(center.Y - radius), (float)(radius * 2), (float)(radius * 2)); } else { List<IntPoint> corners; // is triangle or quadrilateral if (shapeChecker.IsConvexPolygon(edgePoints, out corners)) { // get sub-type PolygonSubType subType = shapeChecker.CheckPolygonSubType(corners); Pen pen; if (subType == PolygonSubType.Unknown) { pen = (corners.Count == 4) ? redPen : bluePen; } else { pen = (corners.Count == 4) ? brownPen : greenPen; } g.DrawPolygon(pen, ToPointsArray(corners)); } } } yellowPen.Dispose(); redPen.Dispose(); greenPen.Dispose(); bluePen.Dispose(); brownPen.Dispose(); g.Dispose(); // put new image to clipboard Clipboard.SetDataObject(bitmap); // and to picture box pictureBox.Image = bitmap; UpdatePictureBoxPosition(); }
private void BtnCalcAccord_Click(object sender, RoutedEventArgs e) { if (imageLoaded) { Stopwatch stopwatch = new Stopwatch(); stopwatch.Start(); Accord.Imaging.UnmanagedImage unmanagedImage1 = Accord.Imaging.UnmanagedImage.FromManagedImage(GrayScaleImage); Accord.Imaging.BlobCounter bc = new Accord.Imaging.BlobCounter { BackgroundThreshold = Color.Black, CoupledSizeFiltering = true, FilterBlobs = true, MinHeight = 30, MinWidth = 30, MaxHeight = 100, MaxWidth = 100 }; bc.ProcessImage(GrayScaleImage); Bitmap indexMap = AForge.Imaging.Image.Clone(GrayScaleImage); for (int x = 0; x < indexMap.Width; x++) { for (int y = 0; y < indexMap.Height; y++) { indexMap.SetPixel(x, y, System.Drawing.Color.Black); } } System.Drawing.Rectangle[] rects = bc.GetObjectsRectangles(); // process blobs BreadBlob[] breadBlob1 = new BreadBlob[bc.ObjectsCount]; int blobArrayIndex = 0; int blobPt = Convert.ToInt16(txbBlobNum.Text); int blobThreshold = Convert.ToInt16(txbBlobThreshold.Text); if (blobPt > bc.ObjectsCount) { blobPt = bc.ObjectsCount - 1; } StaticsCalculator MuffinStatistics = new StaticsCalculator(); Graphics g = Graphics.FromImage(indexMap); List <Accord.Imaging.Blob> blobList = new List <Accord.Imaging.Blob>(); foreach (Accord.Imaging.Blob blob in bc.GetObjects(GrayScaleImage, false)) { blobList.Add(blob); breadBlob1[blobArrayIndex] = new BreadBlob(); breadBlob1[blobArrayIndex].TopDownThreshold = blobThreshold; byte[,] blobArray = new byte[blob.Rectangle.Width, blob.Rectangle.Height]; for (int x = blob.Rectangle.Left; x < blob.Rectangle.Right; x++) { for (int y = blob.Rectangle.Top; y < blob.Rectangle.Bottom; y++) { System.Drawing.Color tempPixelColor = GrayScaleImage.GetPixel(x, y); blobArray[x - blob.Rectangle.Left, y - blob.Rectangle.Top] = tempPixelColor.G; } } breadBlob1[blobArrayIndex].PixelArray = blobArray; breadBlob1[blobArrayIndex].X = blob.Rectangle.X; breadBlob1[blobArrayIndex].Y = blob.Rectangle.Y; if (blobArrayIndex == blobPt) { System.Drawing.Rectangle tempRect = blob.Rectangle; tempRect.X -= 1; tempRect.Y -= 1; tempRect.Width += 2; tempRect.Height += 2; Accord.Imaging.Drawing.Rectangle(unmanagedImage1, tempRect, System.Drawing.Color.Yellow); } if (breadBlob1[blobArrayIndex].IsTop()) { Accord.Imaging.Drawing.Rectangle(unmanagedImage1, blob.Rectangle, System.Drawing.Color.Green); } else { Accord.Imaging.Drawing.Rectangle(unmanagedImage1, blob.Rectangle, System.Drawing.Color.Red); } RectangleF rectf = new RectangleF(blob.Rectangle.X, blob.Rectangle.Y, blob.Rectangle.Width, blob.Rectangle.Height); g.SmoothingMode = SmoothingMode.AntiAlias; g.InterpolationMode = InterpolationMode.HighQualityBicubic; g.PixelOffsetMode = PixelOffsetMode.HighQuality; g.DrawString(Convert.ToString(blob.ID - 1), new Font("Arial", 5), System.Drawing.Brushes.White, rectf); lblBlobHeight.Content = blob.Rectangle.Height; lblBlobWidth.Content = blob.Rectangle.Width; blobArrayIndex++; } lblAccordStdDev.Content = blobList[blobPt].ColorStdDev.B; BitmapImage indexMap_temp = ToBitmapImage(indexMap); g.Flush(); // conver to managed image if it is required to display it at some point of time Bitmap managedImage = unmanagedImage1.ToManagedImage(); // create filter Add filter = new Add(indexMap); // apply the filter Bitmap resultImage = filter.Apply(managedImage); BitmapImage GrayImage_temp = ToBitmapImage(resultImage); imgGray.Source = GrayImage_temp; stopwatch.Stop(); lblTime.Content = stopwatch.ElapsedMilliseconds; lblBlobCount.Content = bc.ObjectsCount; lblLib.Content = "Accord"; lblVariance.Content = breadBlob1[blobPt].GetVariance(BreadBlob.VarianceType.All); lblX.Content = breadBlob1[blobPt].X; lblY.Content = breadBlob1[blobPt].Y; lblQ1Variance.Content = ""; lblQ2Variance.Content = ""; lblQ3Variance.Content = ""; lblQ4Variance.Content = ""; lblQAverage.Content = breadBlob1[blobPt].GetVariance(BreadBlob.VarianceType.QAverage); //lblAllMuffinStat.Content = MuffinStatistics.StandardDeviation; } }
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); } }
/// <summary> /// Initializes a new instance of the <see cref="HslBlobTracker"/> class. /// </summary> /// /// <param name="filter">The filter.</param> /// public HslBlobTracker(HSLFiltering filter) { this.filter = filter; this.blobCounter = new BlobCounter(); this.trackingObject = new TrackingObject(); blobCounter.CoupledSizeFiltering = false; blobCounter.FilterBlobs = true; }
private void captureHand(UnmanagedImage mask, Rectangle rect, PictureBox pbArm, PictureBox pbHand) { Crop c = new Crop(rect); var handImage = c.Apply(mask); var ps = handImage.Collect16bppPixelValues(handImage.CollectActivePixels()); if (ps.Length > 0) { ushort max = Matrix.Max(ps); LevelsLinear16bpp levels = new LevelsLinear16bpp(); levels.InGray = new IntRange(0, max); levels.OutGray = new IntRange(0, 65535); levels.ApplyInPlace(handImage); // pbArm.Image = handImage.ToManagedImage(); double cutoff = 30000; Threshold th = new Threshold((int)cutoff); var handMask = th.Apply(handImage); var handMask8bit = Accord.Imaging.Image.Convert16bppTo8bpp(handMask.ToManagedImage()); BlobCounter bch = new BlobCounter(); bch.ObjectsOrder = ObjectsOrder.Area; bch.ProcessImage(handMask8bit); var blob = bch.GetObjectsInformation(); if (blob.Length > 0) { Intersect inters = new Intersect(); inters.UnmanagedOverlayImage = handMask; inters.ApplyInPlace(handImage); Crop ch = new Crop(blob[0].Rectangle); handImage = ch.Apply(handImage); ResizeNearestNeighbor res = new ResizeNearestNeighbor(25, 25); handImage = res.Apply(handImage); var leftHand = Accord.Imaging.Image.Convert16bppTo8bpp(handImage.ToManagedImage()); pbHand.Image = leftHand; } } }
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(); }