using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.Structure; using bbiwarg.Images; using bbiwarg.Detectors.Fingers; using bbiwarg.Detectors.Palm; using bbiwarg.Utility; using bbiwarg.Graphics; namespace bbiwarg.Detectors.Touch { class TouchDetector { private DepthImage depthImage; private OutputImage outputImage; private List fingers; public List TouchEvents { get; private set; } public TouchDetector(List fingers, DepthImage depthImage, OutputImage outputImage) { this.depthImage = depthImage; this.outputImage = outputImage; this.fingers = fingers; this.TouchEvents = new List(); float floodValueThreshold = 0.33f; foreach (Finger finger in fingers) { Vector2D tipPoint = finger.Tip; float floodValue = getFloodValue(tipPoint); if (floodValue > floodValueThreshold) { //correct touchEvent position Vector2D direction = finger.LineSegment.Line.Direction; float directionFactor = 10; float x = HelperFunctions.thresholdRange(0, depthImage.Width - 1, tipPoint.X + directionFactor * direction.X); float y = HelperFunctions.thresholdRange(0, depthImage.Height - 1, tipPoint.Y + directionFactor * direction.Y); Vector2D tep = new Vector2D(x, y); outputImage.fillCircle(tep.IntX, tep.IntY, 5, Constants.TouchEventDetectedColor); TouchEvent touchEvent = new TouchEvent(tep, floodValue, finger); TouchEvents.Add(touchEvent); } } } private float getFloodValue(Point touchPoint) { int searchSize = 15; int maxDepthDifference = 20; Int16 fingerDiameter = 5; Int16 depthAtTouch = (Int16)(depthImage.getDepthAt(touchPoint) + fingerDiameter); int minX = Math.Max(touchPoint.X - searchSize, 0); int maxX = Math.Min(touchPoint.X + searchSize, depthImage.Width); int minY = Math.Max(touchPoint.Y - searchSize, 0); int maxY = Math.Min(touchPoint.Y + searchSize, depthImage.Height); int matchedPixels = 0; int countedPixels = 0; for (int x = minX; x < maxX; x++) { for (int y = minY; y < maxY; y++) { Int16 depth = depthImage.getDepthAt(x, y); Color color = outputImage.getColotAt(x, y); Color subtractColor; if (depthAtTouch < depth && Math.Abs(depthAtTouch - depth) < maxDepthDifference) { matchedPixels++; subtractColor = Constants.TouchEventAreaMatchedSubtractColor; } else { subtractColor = Constants.TouchEventAreaNonMatchedSubtractColor; } Color newColor = Color.FromArgb(Math.Max(color.R - subtractColor.R, 0), Math.Max(color.G - subtractColor.G, 0), Math.Max(color.B - subtractColor.B, 0)); outputImage.drawPixel(x, y, newColor); countedPixels++; } } float rel = (float)matchedPixels / (float)countedPixels; //status bar (% of matched pixels) -> green for (int x = minX; x < minX + (maxX - minX) * rel; x++) { outputImage.drawPixel(x, maxY - 1, Constants.TouchEventStatusBarColor); } return rel; } } }