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;
     }
 }
示例#3
0
        /// <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);
        }
示例#4
0
        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);
        }