public void Visualize(ISimpleBitmap surface) { int w = surface.PixelWidth; int h = surface.PixelHeight; int[] pixels = surface.Pixels; YCbCrColor min = Min; YCbCrColor max = Max; int i; float xf, yf, cb, cr; // Use constant Y float v = min.Y + (max.Y - min.Y)*YFactor; // Interpolate between min and max and set pixel for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { i = y*w + x; xf = (float) x/w; yf = (float) y/h; cb = min.Cb + (max.Cb - min.Cb)*xf; cr = min.Cr + (max.Cr - min.Cr)*yf; pixels[y*w + x] = new YCbCrColor(v, cb, cr).ToArgbColori(); } } }
public void Visualize(ISimpleBitmap surface) { var w = surface.PixelWidth; var h = surface.PixelHeight; var scale = this.Scale; var histogram = this.Histogram; var histX = histogram.X; var histY = histogram.Y; // Histogram X for (int x = 0; x < w; x++) { var hx = histX[x]; if (hx != 0) { var norm = (int)(((float)hx / histogram.Max.X) * scale); surface.DrawLine(x, h - 1, x, h - norm, Colors.Green); } } // Draw 3 times due to resizing a one pixel line might not be visible if (this.ShowMax) { surface.DrawLine(histogram.MaxIndex.X - 1, h - 1, histogram.MaxIndex.X - 1, 0, Colors.Yellow); surface.DrawLine(histogram.MaxIndex.X, h - 1, histogram.MaxIndex.X, 0, Colors.Yellow); surface.DrawLine(histogram.MaxIndex.X + 1, h - 1, histogram.MaxIndex.X + 1, 0, Colors.Yellow); } // Histogram Y for (int y = 0; y < h; y++) { var hy = histY[y]; if (hy != 0) { var norm = (int)(((float)hy / histogram.Max.Y) * scale); surface.DrawLine(w - 1, y, w - norm, y, Colors.Blue); } } // Draw 3 times due to resizing a one pixel line might not be visible if (this.ShowMax) { surface.DrawLine(w - 1, histogram.MaxIndex.Y - 1, 0, histogram.MaxIndex.Y - 1, Colors.Yellow); surface.DrawLine(w - 1, histogram.MaxIndex.Y, 0, histogram.MaxIndex.Y, Colors.Yellow); surface.DrawLine(w - 1, histogram.MaxIndex.Y + 1, 0, histogram.MaxIndex.Y + 1, Colors.Yellow); } }
public IEnumerable<Segment> Process(ISimpleBitmap bmpToProcess) { if (bmpToProcess == null) return null; ISimpleBitmap skin = SkinColorFilter.Process(bmpToProcess); ISimpleBitmap erode = _erodeFilter.Process(skin); ISimpleBitmap dilate = _dilateFilter.Process(erode); dilate = _dilateFilter.Process(dilate); dilate = _dilateFilter.Process(dilate); Histogram histogram = Histogram.FromWriteableBitmap(dilate); _segmentator.Histogram = histogram; _segmentator.ThresholdLuminance = histogram.Max*0.1f; IEnumerable<Segment> foundSegments = _segmentator.Process(dilate); return foundSegments; }
public override ISimpleBitmap Process(ISimpleBitmap input) { int[] p = input.Pixels; ISimpleBitmap result = Factory.Create(input.PixelWidth, input.PixelHeight); int[] rp = result.Pixels; int r = ResultColor; YCbCrColor ycbcr; // Threshold every pixel for (int i = 0; i < p.Length; i++) { ycbcr = YCbCrColor.FromArgbColori(p[i]); if (ycbcr.Y >= LowerThreshold.Y && ycbcr.Y <= UpperThreshold.Y && ycbcr.Cb >= LowerThreshold.Cb && ycbcr.Cb <= UpperThreshold.Cb && ycbcr.Cr >= LowerThreshold.Cr && ycbcr.Cr <= UpperThreshold.Cr) { rp[i] = r; } } return result; }
public IEnumerable<Segment> Process(ISimpleBitmap input) { if (Histogram == null) { throw new InvalidOperationException("The histogram must be provided"); } int[] hx = Histogram.X; int[] hy = Histogram.Y; Vector histUpperThreshold = Histogram.Max*0.5f; // Find seeds for the segmentation: // All the x and y histogram indices where the value is above the half maximum and have a min distance const int step = 10; // x List<int> ix = GetIndicesAboveThreshold(Histogram.MaxIndex.X, -step, hx, histUpperThreshold.X); ix.AddRange(GetIndicesAboveThreshold(Histogram.MaxIndex.X + step, step, hx, histUpperThreshold.X)); // y List<int> iy = GetIndicesAboveThreshold(Histogram.MaxIndex.Y, -step, hy, histUpperThreshold.Y); iy.AddRange(GetIndicesAboveThreshold(Histogram.MaxIndex.Y + step, step, hy, histUpperThreshold.Y)); // Find the boundaries for the segments defined by the seeds var segments = new List<Segment>(); foreach (int y0 in iy) { foreach (int x0 in ix) { var segment = new Segment(0, 0, 0, 0); segment.Min.X = GetIndexBelowThreshold(x0, -1, hx, ThresholdLuminance.X); segment.Max.X = GetIndexBelowThreshold(x0, 1, hx, ThresholdLuminance.X); segment.Min.Y = GetIndexBelowThreshold(y0, -1, hy, ThresholdLuminance.Y); segment.Max.Y = GetIndexBelowThreshold(y0, 1, hy, ThresholdLuminance.Y); segments.Add(segment); } } if (segments.Count > 0) { // Sort (only pick the largest for now) Segment foundSegment = segments.OrderByDescending(s => s.DiagonalSq).FirstOrDefault(); // Prevent jittering: // If the position doesn't change too much over a certain timespan, the last segment is always returned. // Check for jittering position. bool isJittering = true; if ((lastSegment.Min - foundSegment.Min).LengthSq < jitteringAmountThresholdSq) { // Check for jittering size if (System.Math.Abs(foundSegment.DiagonalSq - lastSegment.DiagonalSq) < jitteringAmountThresholdSq) { jitteringCount++; isJittering = false; } } // Freeze or not if (isJittering) { jitteringCount = 0; } if (jitteringCount < JitteringCountThreshold) { lastSegment = foundSegment; } } return new List<Segment> {lastSegment}; }
public abstract ISimpleBitmap Process(ISimpleBitmap input);
public static Histogram FromWriteableBitmap(ISimpleBitmap input) { int[] p = input.Pixels; int w = input.PixelWidth; int h = input.PixelHeight; var histX = new int[w]; var histY = new int[h]; int empty = CompareEmptyColor; // = 0 // Create row and column statistics / histogram for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++) { if (p[y*w + x] != empty) { histX[x]++; histY[y]++; } } } return new Histogram(histX, histY); }
public override ISimpleBitmap Process(ISimpleBitmap input) { int[] p = input.Pixels; int w = input.PixelWidth; int h = input.PixelHeight; ISimpleBitmap result = Factory.Create(w, h); int[] rp = result.Pixels; int r = ResultColor; int empty = CompareEmptyColor; int c, cm; int i = 0; // Dilate every pixel for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, i++) { // Middle pixel cm = p[y*w + x]; // Is the pixel empty? // If not we set the result and continue with the next pixel if (cm != empty) { rp[i] = r; continue; } // Row 0 // Left pixel if (x - 2 > 0 && y - 2 > 0) { c = p[(y - 2)*w + (x - 2)]; // If only one of the neighboring pixels is not empty, // we set the result and continue with the next pixel. if (c != empty) { rp[i] = r; continue; } } // Middle left pixel if (x - 1 > 0 && y - 2 > 0) { c = p[(y - 2)*w + (x - 1)]; if (c != empty) { rp[i] = r; continue; } } if (y - 2 > 0) { c = p[(y - 2)*w + x]; if (c != empty) { rp[i] = r; continue; } } if (x + 1 < w && y - 2 > 0) { c = p[(y - 2)*w + (x + 1)]; if (c != empty) { rp[i] = r; continue; } } if (x + 2 < w && y - 2 > 0) { c = p[(y - 2)*w + (x + 2)]; if (c != empty) { rp[i] = r; continue; } } // Row 1 // Left pixel if (x - 2 > 0 && y - 1 > 0) { c = p[(y - 1)*w + (x - 2)]; if (c != empty) { rp[i] = r; continue; } } if (x - 1 > 0 && y - 1 > 0) { c = p[(y - 1)*w + (x - 1)]; if (c != empty) { rp[i] = r; continue; } } if (y - 1 > 0) { c = p[(y - 1)*w + x]; if (c != empty) { rp[i] = r; continue; } } if (x + 1 < w && y - 1 > 0) { c = p[(y - 1)*w + (x + 1)]; if (c != empty) { rp[i] = r; continue; } } if (x + 2 < w && y - 1 > 0) { c = p[(y - 1)*w + (x + 2)]; if (c != empty) { rp[i] = r; continue; } } // Row 2 if (x - 2 > 0) { c = p[y*w + (x - 2)]; if (c != empty) { rp[i] = r; continue; } } if (x - 1 > 0) { c = p[y*w + (x - 1)]; if (c != empty) { rp[i] = r; continue; } } if (x + 1 < w) { c = p[y*w + (x + 1)]; if (c != empty) { rp[i] = r; continue; } } if (x + 2 < w) { c = p[y*w + (x + 2)]; if (c != empty) { rp[i] = r; continue; } } // Row 3 if (x - 2 > 0 && y + 1 < h) { c = p[(y + 1)*w + (x - 2)]; if (c != empty) { rp[i] = r; continue; } } if (x - 1 > 0 && y + 1 < h) { c = p[(y + 1)*w + (x - 1)]; if (c != empty) { rp[i] = r; continue; } } if (y + 1 < h) { c = p[(y + 1)*w + x]; if (c != empty) { rp[i] = r; continue; } } if (x + 1 < w && y + 1 < h) { c = p[(y + 1)*w + (x + 1)]; if (c != empty) { rp[i] = r; continue; } } if (x + 2 < w && y + 1 < h) { c = p[(y + 1)*w + (x + 2)]; if (c != empty) { rp[i] = r; continue; } } // Row 4 if (x - 2 > 0 && y + 2 < h) { c = p[(y + 2)*w + (x - 2)]; if (c != empty) { rp[i] = r; continue; } } if (x - 1 > 0 && y + 2 < h) { c = p[(y + 2)*w + (x - 1)]; if (c != empty) { rp[i] = r; continue; } } if (y + 2 < h) { c = p[(y + 2)*w + x]; if (c != empty) { rp[i] = r; continue; } } if (x + 1 < w && y + 2 < h) { c = p[(y + 2)*w + (x + 1)]; if (c != empty) { rp[i] = r; continue; } } if (x + 2 < w && y + 2 < h) { c = p[(y + 2)*w + (x + 2)]; if (c != empty) { rp[i] = r; continue; } } } } return result; }
public override ISimpleBitmap Process(ISimpleBitmap input) { int[] p = input.Pixels; int w = input.PixelWidth; int h = input.PixelHeight; ISimpleBitmap result = Factory.Create(w, h); int[] rp = result.Pixels; int empty = CompareEmptyColor; int c, cm; int i = 0; // Erode every pixel for (int y = 0; y < h; y++) { for (int x = 0; x < w; x++, i++) { // Middle pixel cm = p[y*w + x]; if (cm == empty) { continue; } // Row 0 // Left pixel if (x - 2 > 0 && y - 2 > 0) { c = p[(y - 2)*w + (x - 2)]; if (c == empty) { continue; } } // Middle left pixel if (x - 1 > 0 && y - 2 > 0) { c = p[(y - 2)*w + (x - 1)]; if (c == empty) { continue; } } if (y - 2 > 0) { c = p[(y - 2)*w + x]; if (c == empty) { continue; } } if (x + 1 < w && y - 2 > 0) { c = p[(y - 2)*w + (x + 1)]; if (c == empty) { continue; } } if (x + 2 < w && y - 2 > 0) { c = p[(y - 2)*w + (x + 2)]; if (c == empty) { continue; } } // Row 1 // Left pixel if (x - 2 > 0 && y - 1 > 0) { c = p[(y - 1)*w + (x - 2)]; if (c == empty) { continue; } } if (x - 1 > 0 && y - 1 > 0) { c = p[(y - 1)*w + (x - 1)]; if (c == empty) { continue; } } if (y - 1 > 0) { c = p[(y - 1)*w + x]; if (c == empty) { continue; } } if (x + 1 < w && y - 1 > 0) { c = p[(y - 1)*w + (x + 1)]; if (c == empty) { continue; } } if (x + 2 < w && y - 1 > 0) { c = p[(y - 1)*w + (x + 2)]; if (c == empty) { continue; } } // Row 2 if (x - 2 > 0) { c = p[y*w + (x - 2)]; if (c == empty) { continue; } } if (x - 1 > 0) { c = p[y*w + (x - 1)]; if (c == empty) { continue; } } if (x + 1 < w) { c = p[y*w + (x + 1)]; if (c == empty) { continue; } } if (x + 2 < w) { c = p[y*w + (x + 2)]; if (c == empty) { continue; } } // Row 3 if (x - 2 > 0 && y + 1 < h) { c = p[(y + 1)*w + (x - 2)]; if (c == empty) { continue; } } if (x - 1 > 0 && y + 1 < h) { c = p[(y + 1)*w + (x - 1)]; if (c == empty) { continue; } } if (y + 1 < h) { c = p[(y + 1)*w + x]; if (c == empty) { continue; } } if (x + 1 < w && y + 1 < h) { c = p[(y + 1)*w + (x + 1)]; if (c == empty) { continue; } } if (x + 2 < w && y + 1 < h) { c = p[(y + 1)*w + (x + 2)]; if (c == empty) { continue; } } // Row 4 if (x - 2 > 0 && y + 2 < h) { c = p[(y + 2)*w + (x - 2)]; if (c == empty) { continue; } } if (x - 1 > 0 && y + 2 < h) { c = p[(y + 2)*w + (x - 1)]; if (c == empty) { continue; } } if (y + 2 < h) { c = p[(y + 2)*w + x]; if (c == empty) { continue; } } if (x + 1 < w && y + 2 < h) { c = p[(y + 2)*w + (x + 1)]; if (c == empty) { continue; } } if (x + 2 < w && y + 2 < h) { c = p[(y + 2)*w + (x + 2)]; if (c == empty) { continue; } } // If all neighboring pixels are processed // it's clear that the current pixel is not a boundary pixel. rp[i] = cm; } } return result; }