TouchDetector.cs 3.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. using Emgu.CV;
  8. using Emgu.CV.Structure;
  9. using bbiwarg.Images;
  10. using bbiwarg.Recognition.FingerRecognition;
  11. using bbiwarg.Recognition.PalmRecognition;
  12. using bbiwarg.Utility;
  13. using bbiwarg.Output;
  14. using bbiwarg.Input.InputHandling;
  15. namespace bbiwarg.Recognition.TouchRecognition
  16. {
  17. class TouchDetector
  18. {
  19. private DepthImage depthImage;
  20. private List<Finger> fingers;
  21. private List<Palm> palms;
  22. private List<Touch> touches;
  23. public void detectTouches(FrameData frameData)
  24. {
  25. depthImage = frameData.DepthImage;
  26. fingers = frameData.TrackedFingers;
  27. palms = frameData.TrackedPalms;
  28. touches = new List<Touch>();
  29. if (palms.Count > 0)
  30. detectTouch();
  31. frameData.DetectedTouches = touches;
  32. }
  33. private void detectTouch()
  34. {
  35. foreach (Finger finger in fingers)
  36. {
  37. Vector2D tipPoint = finger.TipPoint;
  38. Vector2D direction = finger.Direction;
  39. Vector2D tipPointInside = tipPoint.moveWithinBound(depthImage.Size, direction.getInverse(), Parameters.TouchTipInsideFactor);
  40. Vector2D tipPointOutside = tipPoint.moveWithinBound(depthImage.Size, direction, Parameters.TouchTipOutsideFactor);
  41. foreach (Palm palm in palms)
  42. {
  43. if (palm.isInside(tipPointOutside))
  44. {
  45. Image<Gray, byte> touchMask = getTouchMask(tipPointInside);
  46. int touchPixels = touchMask.CountNonzero()[0];
  47. int numPixels = touchMask.Width * touchMask.Height;
  48. float touchValue = touchPixels / (float)numPixels;
  49. if (touchValue > Parameters.TouchMinTouchValue)
  50. {
  51. Touch touchEvent = new Touch(tipPointOutside, finger, palm);
  52. touches.Add(touchEvent);
  53. }
  54. }
  55. }
  56. }
  57. }
  58. private Image<Gray, byte> getTouchMask(Vector2D touchPoint)
  59. {
  60. int minX = Math.Max(touchPoint.IntX - 2 * Parameters.TouchAreaSize / 3, 0);
  61. int maxX = Math.Min(touchPoint.IntX + Parameters.TouchAreaSize / 3, depthImage.Size.Width - 1);
  62. int minY = Math.Max(touchPoint.IntY - 2 * Parameters.TouchAreaSize / 3, 0);
  63. int maxY = Math.Min(touchPoint.IntY + Parameters.TouchAreaSize / 3, depthImage.Size.Height - 1);
  64. Vector2D relTouchPoint = new Vector2D(touchPoint.IntX - minX, touchPoint.IntY - minY);
  65. Rectangle rect = new Rectangle(minX, minY, maxX - minX + 1, maxY - minY + 1);
  66. Image<Gray, byte> touchArea = depthImage.Image.Copy(rect);
  67. Image<Gray, byte> touchMask = new Image<Gray, byte>(rect.Width + 2, rect.Height + 2);
  68. MCvConnectedComp comp = new MCvConnectedComp();
  69. 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);
  70. Rectangle cropRect = new Rectangle(1, 1, rect.Width, rect.Height);
  71. return touchMask.Copy(cropRect);
  72. }
  73. }
  74. }