private void DrawBlobBorderOnImage(PixelBlob blob, BitmapSource image) { if (image == null) { return; } DrawingVisual dv = new DrawingVisual(); var src = image; using (DrawingContext dc = dv.RenderOpen()) { dc.DrawImage(src, new Rect(0, 0, src.PixelWidth, src.PixelHeight)); if (blob != null) { var brush = new SolidColorBrush(Colors.White); var pen = new Pen(brush, 5); var size = new Size(1, 1); blob.Border.ForEach(pixel => dc.DrawRectangle(brush, pen, new Rect(pixel.Position, size))); } } RenderTargetBitmap rtb = new RenderTargetBitmap(src.PixelWidth, src.PixelHeight, 96, 96, PixelFormats.Pbgra32); rtb.Render(dv); this.SourceImageFacade = this.CopyImageToWriteableBitmap(rtb); }
public PixelBlobViewModel(PixelBlob model) { this.model = model; this.IsEditting = false; if (string.IsNullOrEmpty(this.Name)) { this.Name = this.HexColor; } }
/// <summary> /// Forward-only blob search /// </summary> private PixelBlob FindBlob(PixelData data) { PixelBlob blob = null; PixelBlob currentBlob = null; PixelDataList pixels = null; bool isNeighbor = false; for (int b = this.Blobs.Count - 1; b >= 0 && blob == null; b--) { currentBlob = this.Blobs[b]; pixels = null; isNeighbor = false; if (currentBlob.Pixels.Count > 0) { pixels = currentBlob.Pixels[currentBlob.Pixels.Count - 1]; // Same Y-Index as the current pixel if (pixels.Y == data.Y) { if (Math.Abs(pixels[pixels.Count - 1].X - data.X) <= 1) { isNeighbor = true; } } // Previous Y-index as the current pixel else if (pixels.Y == (data.Y - 1)) { // Iterate through the y position for (int x = 0; x < pixels.Count && !isNeighbor; x++) { if (Math.Abs(pixels[x].X - data.X) == 0) { isNeighbor = true; } } } // If the current blob neighbors the current pixel. Check the threshold if (isNeighbor && Math.Abs(data.Red - currentBlob.AverageR) <= this.ToleranceR && Math.Abs(data.Green - currentBlob.AverageG) <= this.ToleranceG && Math.Abs(data.Blue - currentBlob.AverageB) <= this.ToleranceB) { blob = currentBlob; } } } return(blob); }
protected override unsafe void ProcessFilter(UnmanagedImage image) { //TODO: Empty image / 0 pixels / division by 0 PixelData data; //IntPtr scan0 = image.Scan0; //int stride = image.Stride; int offset = (image.Stride - image.Width * 3); // Calc running total of pixel values for standard deviation double totalR = 0; double totalG = 0; double totalB = 0; byte *ptr = (byte *)image.ImageData.ToPointer(); for (int y = 0; y < image.Height; y++) { for (int x = 0; x < image.Width; x++, ptr += 3) { // Get pixel data for all channels data = new PixelData(); data.Red = ptr[RGB.R]; data.Green = ptr[RGB.G]; data.Blue = ptr[RGB.B]; data.X = x; data.Y = y; data.Ptr = ptr; this.Pixels.Add(data); totalR += data.Red; totalG += data.Green; totalB += data.Blue; } ptr += offset; } // Total variances of pixel channels for standard deviation double varianceR = 0; double varianceG = 0; double varianceB = 0; double averageR = totalR / this.Pixels.Count; double averageG = totalG / this.Pixels.Count; double averageB = totalB / this.Pixels.Count; for (int p = 0; p < this.Pixels.Count; p++) { varianceR += Math.Pow(this.Pixels[p].Red - averageR, 2); varianceG += Math.Pow(this.Pixels[p].Green - averageG, 2); varianceB += Math.Pow(this.Pixels[p].Blue - averageB, 2); } // Calculate standard deviation of each channel double deviationR = Math.Sqrt(varianceR / this.Pixels.Count); double deviationG = Math.Sqrt(varianceG / this.Pixels.Count); double deviationB = Math.Sqrt(varianceB / this.Pixels.Count); this.ToleranceR = deviationR * this.ToleranceFactor; this.ToleranceG = deviationG * this.ToleranceFactor; this.ToleranceB = deviationB * this.ToleranceFactor; // Generate blobs from the image for (int p = 0; p < this.Pixels.Count; p++) { // Attempt to find a blob to belong to PixelBlob blob = this.FindBlob(this.Pixels[p]); if (blob == null) { // No blob found -- create a new one blob = new PixelBlob(); this.Blobs.Add(blob); } // Add the current pixel to the blob blob.AddPixel(this.Pixels[p]); } // Traverse pixels again, this time to set them to blob averages for (int b = 0; b < this.Blobs.Count; b++) { PixelBlob currentBlob = this.Blobs[b]; // Y pixels foreach (PixelDataList pixel in currentBlob.Pixels) { // X pixels foreach (PixelData pixelData in pixel) { pixelData.Ptr[RGB.R] = currentBlob.AverageR; pixelData.Ptr[RGB.G] = currentBlob.AverageG; pixelData.Ptr[RGB.B] = currentBlob.AverageB; } } } }
private List <PixelBlob> ProcessPixelGroup(IGrouping <PixelColor, Pixel> pixelGroup, IPixelsSource pixelsSource, ITaskContext taskContext) { var pixelGroupList = pixelGroup.ToList(); var keyDisplayName = pixelGroup.Key.ToColor().ToHexString(); var groupBlobs = new List <PixelBlob>(); try { double originalCount = (double)pixelGroupList.Count; Func <int> calculatePercentage = () => { return(Math.Min((int)(100 - (((double)pixelGroupList.Count / originalCount) * 100)), 99)); }; int percentageDone = 0; Action updatePercentage = () => { taskContext.UpdateMessage($"{keyDisplayName}: Processing pixel group. {pixelGroupList.Count} left out of {originalCount}"); percentageDone = calculatePercentage(); taskContext.UpdateProgress(percentageDone); //Only go up to 99 so the task doesn't end. }; while (pixelGroupList.Count > 0) { updatePercentage(); var nextPixel = pixelGroupList.First(); var blobPixels = new List <Pixel>(); var currentList = new List <Pixel>(); currentList.Add(nextPixel); var siblingTransferList = new List <Pixel>(); do { blobPixels.AddRange(currentList); currentList.ForEach ( x => { pixelGroupList.Remove(x); foreach (var sibling in pixelsSource.GetSiblings(x, true)) { if (sibling == null || blobPixels.Contains(sibling) || siblingTransferList.Contains(sibling)) { continue; } siblingTransferList.Add(sibling); } } ); currentList.Clear(); currentList.AddRange(siblingTransferList); siblingTransferList.Clear(); updatePercentage(); }while (currentList.Any()); var blob = new PixelBlob(pixelsSource) { BlobColor = pixelGroup.Key, Pixels = blobPixels }; groupBlobs.Add(blob); pixelGroupList = pixelGroupList.Where(pixel => !blobPixels.Contains(pixel)).ToList(); } taskContext.UpdateMessage($"{keyDisplayName}: {groupBlobs.Count} blobs."); taskContext.UpdateProgress(100); } catch (Exception ex) { string stopHere = ex.Message; } return(groupBlobs); }