public static BlobAnalysisResult Analyze(this BlobContainer blob, int?frameXOffset = null, int?frameYOffset = null, int?frameXLength = null, int?frameYLength = null) { var mass = 0D; var xAggregate = 0D; var yAggregate = 0D; foreach (var c in blob.Points) { mass += c.Color.TotalBrightness(); xAggregate += c.Location.X; yAggregate += c.Location.Y; } if (mass == 0) { return(null); } var response = new BlobAnalysisResult { Mass = mass, CentroidX = xAggregate / mass, CentroidY = yAggregate / mass, OriginalBlob = blob }; var radiusComponents = new List <double>(); var paddingComponents = new List <double>(); var xOffset = frameXOffset ?? blob.Points.Min(a => a.Location.X); var yOffset = frameYOffset ?? blob.Points.Min(a => a.Location.Y); var xLength = frameXLength ?? (blob.Points.Max(a => a.Location.X) - xOffset); var yLength = frameYLength ?? (blob.Points.Max(a => a.Location.Y) - yOffset); foreach (var c in blob.Points) { var radius = Math.Sqrt(Math.Pow(c.Location.X - response.CentroidX, 2) + Math.Pow(c.Location.Y - response.CentroidY, 2)); var weighted = radius * c.Color.TotalBrightness(); radiusComponents.Add(weighted); paddingComponents.Add(Util.AbsMin(c.Location.X - xOffset, c.Location.X - (xOffset + xLength), c.Location.Y - yOffset, c.Location.Y - (yOffset + yLength))); } response.MeanRadius = radiusComponents.Average(); response.MedianRadius = radiusComponents.Median(); response.MeanPadding = paddingComponents.Average(); response.MedianPadding = paddingComponents.Median(); return(response); }
public static ICollection <BlobContainer> SplitToBlobs(this Bitmap bitmap, int?minimumBlobMass = 3) { var nonEmptyPixels = bitmap.ParseBitmap() .Where(a => a.Color.TotalBrightness() > 0.5); var blobs = new List <BlobContainer>(); var blobMap = new Dictionary <Point, BlobContainer>(); foreach (var locus in nonEmptyPixels) { Console.WriteLine("Parsing ({0}, {1})", locus.Location.X, locus.Location.Y); var adjacentPoints = new List <Point>(); if (locus.Location.X > 0) { adjacentPoints.Add(new Point(locus.Location.X - 1, locus.Location.Y)); } if (locus.Location.Y > 0) { adjacentPoints.Add(new Point(locus.Location.X, locus.Location.Y - 1)); } if (locus.Location.X < bitmap.Width - 1) { adjacentPoints.Add(new Point(locus.Location.X + 1, locus.Location.Y)); } if (locus.Location.Y < bitmap.Height - 1) { adjacentPoints.Add(new Point(locus.Location.X, locus.Location.Y + 1)); } var matchingBlobs = adjacentPoints .Where(blobMap.ContainsKey) .Select(a => blobMap[a]) .Distinct(); BlobContainer targetBlob = null; foreach (var m in matchingBlobs) { if (targetBlob == null) { targetBlob = m; } else { foreach (var l in m.Points) { targetBlob.Points.Add(l); blobMap[l.Location] = targetBlob; blobs.Remove(m); } } } if (targetBlob == null) { targetBlob = new BlobContainer { Points = new List <ColorPoint>() }; blobs.Add(targetBlob); } targetBlob.Points.Add(locus); blobMap[locus.Location] = targetBlob; } if (minimumBlobMass.HasValue) { blobs.RemoveAll(a => a.Points.Count < minimumBlobMass.Value); } return(blobs); }