IEnumerator <ITask> DoVisionProcessing(VisionProcessingParameters parameters) { try { List <ColorSet> colors = parameters.Colors; Settings settings = parameters.Settings; int[] colorSetMap = parameters.ColorSetMap; webcam.QueryFrameResponse response = null; yield return(Arbiter.Choice( _webcamPort.QueryFrame(), delegate(webcam.QueryFrameResponse success) { response = success; }, LogError )); if (response == null) { yield break; } double threshold = settings.Threshold; int height = response.Size.Height; int width = response.Size.Width; int offset; int stride = response.Frame.Length / height; byte[] bytes = response.Frame; byte[,] indexed = new byte[width, height]; int segOffset; int segStride = width; byte[] segmented = new byte[width * height]; for (int y = 0; y < height; y++) { offset = stride * y; segOffset = segStride * y; for (int x = 0; x < width; x++) { int blu = bytes[offset++]; int grn = bytes[offset++]; int red = bytes[offset++]; int col = (((red + 7) & 0xF0) << 4) | ((grn + 7) & 0xF0) | (((blu + 7) & 0xF0) >> 4); int bestIndex = colorSetMap[col]; indexed[x, y] = (byte)bestIndex; segmented[segOffset++] = (byte)bestIndex; } } if (settings.Despeckle) { int[] votes; byte[,] despeckled = new byte[width, height]; offset = 0; for (int y = 0; y < height; y++) { offset = y * stride; for (int x = 0; x < width; x++, offset++) { votes = new int[colors.Count + 1]; int color; int leader = 0; if (x == 0 || y == 0 || x == width - 1 || y == height - 1) { leader = indexed[x, y]; votes[leader]++; } else { for (int iy = -1; iy < 2; iy++) { for (int ix = -1; ix < 2; ix++) { color = indexed[x + ix, y + iy]; votes[color]++; if (votes[color] > votes[leader]) { leader = color; } } } // // if there is a tie, then use the original color. // int bestVote = votes[leader]; for (int i = 0; i < votes.Length; i++) { if (i != leader && votes[i] == bestVote) { leader = indexed[x, y]; break; } } } despeckled[x, y] = (byte)leader; } } indexed = despeckled; } List <ColorArea> areas = new List <ColorArea>(); byte[,] copy = (byte[, ])indexed.Clone(); for (int y = 0; y < height; y++) { for (int x = 0; x < width; x++) { int curr = copy[x, y]; if (curr != 0) { ColorArea area = new ColorArea(colors[curr - 1].Name); area.Flood(copy, x, y); areas.Add(area); } } } areas = areas.FindAll( delegate(ColorArea test) { return(test.Area >= settings.MinBlobSize); } ); areas.Sort( delegate(ColorArea left, ColorArea right) { return(-left.Area.CompareTo(right.Area)); } ); Color[] outputColors = new Color[colors.Count + 1]; for (int i = 0; i < outputColors.Length; i++) { if (i == 0) { outputColors[i] = Color.Black; } else { ColorSet set = colors[i - 1]; ColorDefinition def = set.Colors[0]; outputColors[i] = Color.FromArgb(def.R, def.G, def.B); } } for (int y = 0; y < height; y++) { offset = y * stride; segOffset = y * segStride; for (int x = 0; x < width; x++) { int palIndex = segmented[segOffset++]; Color pixel = outputColors[palIndex]; bytes[offset++] = (byte)pixel.B; bytes[offset++] = (byte)pixel.G; bytes[offset++] = (byte)pixel.R; } } segmented = bytes; SegmentedImage image = new SegmentedImage(response.TimeStamp, width, height, segmented, indexed); _mainPort.Post(new UpdateSegmentedImage(image)); FoundColorAreas foundColors = new FoundColorAreas(); foundColors.TimeStamp = response.TimeStamp; foreach (ColorArea area in areas) { if (area.Area > 0) { area.Complete(); foundColors.Areas.Add(area); } } _fwdPort.Post(new UpdateColorAreas(foundColors)); } finally { _fwdPort.Post(new ProcessFrame(false)); } }
public UpdateColorAreas(FoundColorAreas body) : base(body) { }