/// <summary> /// Returns the distance from the target color histogram the given pixel array is /// </summary> /// <param name="pixelArray">The pixel array of the bitmap to get the distance of</param> /// <param name="bitmapWidth">The width of the bitmap</param> /// <param name="bitmapHeight">The height of the bitmap</param> /// <param name="stride">The number of bytes per row</param> /// <param name="targetColor">The histogram of the color of the target object</param> /// <returns>The minimum distance a subrect of the image is from the target histogram</returns> private static double GetColorDistance(byte[] pixelArray, int bitmapWidth, int bitmapHeight, int stride, double[] targetColor) { var colorDistancePixelArray = (byte[])pixelArray.Clone(); var pixelArrayLock = new object(); // Threshold the image for possible areas where the object is Parallel.ForEach(ExtensionMethods.SteppedRange(0, bitmapWidth, 8), column => { Parallel.ForEach(ExtensionMethods.SteppedRange(0, bitmapHeight, 8), row => { int width = Math.Min(8, bitmapWidth - column); int height = Math.Min(8, bitmapHeight - row); var croppedPixelArray = pixelArray.CropPixelArray(column, row, width, height, stride); var colorBins = ColorClassifier.GetColorBins(croppedPixelArray, true); var distance = ColorClassifier.CalculateBinDistance(colorBins, targetColor); // Possible areas where the object we are looking for is are black 0 byte newColor = distance >= 125 ? (byte)255 : (byte)0; for (int i = 0; i < width; i++) { for (int j = 0; j < height; j++) { int index = (row + j) * stride + 4 * (column + i); lock ( pixelArrayLock ) { colorDistancePixelArray[index] = colorDistancePixelArray[index + 1] = colorDistancePixelArray[index + 2] = newColor; } } } }); }); // Look at each blob and determine if it is our // object with a stricted threshold var tempBitmap = new WriteableBitmap(bitmapWidth, bitmapHeight, 96, 96, PixelFormats.Bgr32, null); tempBitmap.WritePixels(new Int32Rect(0, 0, bitmapWidth, bitmapHeight), colorDistancePixelArray, stride, 0); double minDistance = double.PositiveInfinity; var allBlobDistance = GetColorBinDistance(pixelArray, colorDistancePixelArray, stride, targetColor, tempBitmap, Colors.Black); if (allBlobDistance <= 105) { minDistance = allBlobDistance; } var blobColors = BitmapColorer.ColorBitmap(tempBitmap); foreach (var color in blobColors) { var distance = GetColorBinDistance(pixelArray, colorDistancePixelArray, stride, targetColor, tempBitmap, color); if (distance <= minDistance) { minDistance = distance; } } return(minDistance); }
private static double GetColorBinDistance(byte[] pixelArray, byte[] thresholdedPixelArray, int stride, double[] targetHistogram, WriteableBitmap tempBitmap, Color color) { var boundingBox = BitmapColorer.GetBoundingBoxOfColor(tempBitmap, color); var croppedPixelArray = pixelArray.CropPixelArray((int)boundingBox.X, (int)boundingBox.Y, (int)boundingBox.Width, (int)boundingBox.Height, stride); var croppedThresholdedArray = thresholdedPixelArray.CropPixelArray((int)boundingBox.X, (int)boundingBox.Y, (int)boundingBox.Width, (int)boundingBox.Height, stride); var colorBins = ColorClassifier.GetColorBinsWithinBlob(croppedPixelArray, croppedThresholdedArray, true); var distance = ColorClassifier.CalculateBinDistance(colorBins, targetHistogram); return(distance); }