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.Recognition.FingerRecognition; using bbiwarg.Recognition.PalmRecognition; using bbiwarg.Utility; using bbiwarg.Graphics; namespace bbiwarg.Recognition.TouchRecognition { class TouchDetector { private DepthImage depthImage; private List fingers; private List palms; public List TouchEvents { get; private set; } public TouchDetector(DepthImage depthImage, List fingers, List palms) { this.depthImage = depthImage; this.fingers = fingers; this.palms = palms; TouchEvents = new List(); if (palms.Count > 0) detectTouch(); } private void detectTouch() { foreach (Finger finger in fingers) { Vector2D tipPoint = finger.TipPoint; Vector2D direction = finger.Direction; Vector2D directionInv = direction.getInverse(); Vector2D tipPointInside = (tipPoint + Parameters.TouchTipInsideFactor * directionInv).moveInBound(direction); Vector2D tipPointOutside = (tipPoint + Parameters.TouchTipOutsideFactor * direction).moveInBound(directionInv); foreach (Palm palm in palms) { if (palm.isInside(tipPointOutside)) { Image touchMask = getTouchMask(tipPointInside); int touchPixels = touchMask.CountNonzero()[0]; int numPixels = touchMask.Width * touchMask.Height; float touchValue = touchPixels / (float)numPixels; if (touchValue > Parameters.TouchMinTouchValue) { TouchEvent touchEvent = new TouchEvent(tipPointOutside, touchMask, finger, palm); TouchEvents.Add(touchEvent); finger.setTouchEvent(touchEvent); } } } } } private Image getTouchMask(Vector2D touchPoint) { int minX = Math.Max(touchPoint.IntX - 2 * Parameters.TouchAreaSize / 3, 0); int maxX = Math.Min(touchPoint.IntX + Parameters.TouchAreaSize / 3, Parameters.ImageWidth - 1); int minY = Math.Max(touchPoint.IntY - 2 * Parameters.TouchAreaSize / 3, 0); int maxY = Math.Min(touchPoint.IntY + Parameters.TouchAreaSize / 3, Parameters.ImageHeight - 1); Vector2D relTouchPoint = new Vector2D(touchPoint.IntX - minX, touchPoint.IntY - minY); Rectangle rect = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1); Image touchArea = depthImage.Image.Copy(rect); Image touchMask = new Image(rect.Width + 2, rect.Height + 2); MCvConnectedComp comp = new MCvConnectedComp(); CvInvoke.cvFloodFill(touchArea, relTouchPoint, new MCvScalar(255), new MCvScalar(Parameters.TouchFloodfillDownDiff), new MCvScalar(Parameters.TouchFloodfillUpDiff), out comp, Emgu.CV.CvEnum.CONNECTIVITY.EIGHT_CONNECTED, Emgu.CV.CvEnum.FLOODFILL_FLAG.DEFAULT, touchMask); Rectangle cropRect = new Rectangle(1, 1, rect.Width, rect.Height); return touchMask.Copy(cropRect); } } }