InputHandler.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  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 bbiwarg.InputProviders;
  8. using bbiwarg.Images;
  9. using bbiwarg.Recognition.FingerRecognition;
  10. using bbiwarg.Recognition.HandRecognition;
  11. using bbiwarg.Recognition.PalmRecognition;
  12. using bbiwarg.Recognition.TouchRecognition;
  13. using bbiwarg.Recognition.Tracking;
  14. using bbiwarg.Server;
  15. using bbiwarg.Graphics;
  16. using bbiwarg.Utility;
  17. using Emgu.CV;
  18. using Emgu.CV.Structure;
  19. namespace bbiwarg
  20. {
  21. class InputHandler
  22. {
  23. public OutputImage[] OutputImages { get; private set; }
  24. private InputProvider inputProvider;
  25. private InputFrame currentInputFrame;
  26. private int imageWidth;
  27. private int imageHeight;
  28. private int currentFrameID;
  29. private int lastFrameID;
  30. private DepthImage depthImage;
  31. private EdgeImage edgeImage;
  32. private ConfidenceImage confidenceImage;
  33. private FingerDetector fingerDetector;
  34. private HandDetector handDetector;
  35. private PalmDetector palmDetector;
  36. private TouchDetector touchDetector;
  37. private FingerTracker fingerTracker;
  38. private TouchTracker touchTracker;
  39. private TouchEventVisualizer touchEventVisualizer;
  40. private TuioCommunicator tuioCommunicator;
  41. public InputHandler(InputProvider inputProvider)
  42. {
  43. this.inputProvider = inputProvider;
  44. this.imageWidth = inputProvider.ImageWidth;
  45. this.imageHeight = inputProvider.ImageHeight;
  46. this.currentFrameID = inputProvider.CurrentFrameID;
  47. this.lastFrameID = this.currentFrameID - 1;
  48. initializeConsistentObjects();
  49. }
  50. private void initializeConsistentObjects()
  51. {
  52. palmDetector = new PalmDetector();
  53. fingerTracker = new FingerTracker();
  54. touchTracker = new TouchTracker();
  55. if (Constants.OutputEnabled)
  56. {
  57. touchEventVisualizer = new TouchEventVisualizer(imageWidth, imageHeight);
  58. //register touchEventVisualizer to touchTracker
  59. touchTracker.TouchDown += touchEventVisualizer.touchDown;
  60. touchTracker.TouchMove += touchEventVisualizer.touchMove;
  61. touchTracker.TouchUp += touchEventVisualizer.touchUp;
  62. }
  63. if (Constants.TuioEnabled)
  64. {
  65. tuioCommunicator = new TuioCommunicator(Constants.TuioIP, Constants.TuioPort);
  66. //register tuiCommunicator to touchTracker
  67. touchTracker.TouchDown += tuioCommunicator.touchDown;
  68. touchTracker.TouchMove += tuioCommunicator.touchMove;
  69. touchTracker.TouchUp += tuioCommunicator.touchUp;
  70. }
  71. }
  72. private void resetConsistentObjects()
  73. {
  74. palmDetector.reset();
  75. touchTracker.reset();
  76. fingerTracker.reset();
  77. if (Constants.OutputEnabled)
  78. touchEventVisualizer.reset();
  79. if (Constants.TuioEnabled)
  80. tuioCommunicator.reset();
  81. }
  82. public void updateFrame()
  83. {
  84. Timer.start("updateFrame");
  85. if (currentFrameID != inputProvider.CurrentFrameID)
  86. {
  87. beforeUpdateFrame();
  88. if (lastFrameID - currentFrameID > 20)
  89. resetConsistentObjects();
  90. createConfidenceImage();
  91. createDepthImage();
  92. createEdgeImage();
  93. detectFingers();
  94. trackFingers();
  95. detectHands();
  96. detectPalm();
  97. detectTouchEvents();
  98. trackTouchEvents();
  99. afterUpdateFrame();
  100. }
  101. Timer.stop("updateFrame");
  102. }
  103. private void beforeUpdateFrame()
  104. {
  105. Timer.start("beforeUpdateFrame");
  106. currentInputFrame = inputProvider.CurrentFrame;
  107. lastFrameID = currentFrameID;
  108. currentFrameID = currentInputFrame.FrameID;
  109. Logger.CurrentFrame = currentFrameID;
  110. if (Constants.TuioEnabled)
  111. tuioCommunicator.initFrame();
  112. Timer.stop("beforeUpdateFrame");
  113. }
  114. private void afterUpdateFrame()
  115. {
  116. Timer.start("afterUpdateFrame");
  117. if (Constants.TuioEnabled)
  118. tuioCommunicator.commitFrame();
  119. if (Constants.OutputEnabled)
  120. createOutputImages();
  121. Timer.stop("afterUpdateFrame");
  122. }
  123. private void createConfidenceImage()
  124. {
  125. Timer.start("createCnfdncImg");
  126. Image<Gray, Int16> rawConfidenceImage = new Image<Gray, Int16>(imageWidth, imageHeight, imageWidth * 2, currentInputFrame.RawConfidenceData);
  127. confidenceImage = new ConfidenceImage(rawConfidenceImage);
  128. Timer.stop("createCnfdncImg");
  129. }
  130. private void createDepthImage()
  131. {
  132. Timer.start("createDepthImage");
  133. Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(imageWidth, imageHeight, imageWidth * 2, currentInputFrame.RawDepthData);
  134. rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));
  135. depthImage = new DepthImage(rawDepthImage);
  136. Timer.stop("createDepthImage");
  137. }
  138. private void createEdgeImage()
  139. {
  140. Timer.start("createEdgeImage");
  141. edgeImage = new EdgeImage(depthImage);
  142. Timer.stop("createEdgeImage");
  143. }
  144. private void detectFingers()
  145. {
  146. Timer.start("detectFingers");
  147. fingerDetector = new FingerDetector(depthImage, edgeImage);
  148. Timer.stop("detectFingers");
  149. }
  150. private void trackFingers()
  151. {
  152. Timer.start("trackFingers");
  153. fingerTracker.updateFrame(fingerDetector.Fingers);
  154. Timer.stop("trackFingers");
  155. }
  156. private void detectHands()
  157. {
  158. Timer.start("detectHands");
  159. handDetector = new HandDetector(edgeImage, fingerDetector.Fingers);
  160. Timer.stop("detectHands");
  161. }
  162. private void detectPalm()
  163. {
  164. Timer.start("detectPalmQuad");
  165. palmDetector.findPalmQuad(handDetector.Hands, handDetector.HandMask);
  166. Timer.stop("detectPalmQuad");
  167. }
  168. private void detectTouchEvents()
  169. {
  170. Timer.start("detectTouchEvents");
  171. touchDetector = new TouchDetector(depthImage, fingerTracker.Fingers, palmDetector.PalmQuad);
  172. Timer.stop("detectTouchEvents");
  173. }
  174. private void trackTouchEvents()
  175. {
  176. Timer.start("trackTouchEvents");
  177. touchTracker.updateFrame(touchDetector.TouchEvents);
  178. Timer.stop("trackTouchEvents");
  179. }
  180. private void createOutputImages()
  181. {
  182. Timer.start("createOutputImages");
  183. int numImages = Constants.OutputNumImages;
  184. OutputImages = new OutputImage[numImages];
  185. for (int i = 0; i < numImages; i++)
  186. {
  187. OutputImages[i] = new OutputImage(imageWidth, imageHeight);
  188. }
  189. //image0
  190. OutputImages[0].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image, Constants.DepthImageColor);
  191. foreach (Finger f in fingerTracker.Fingers)
  192. {
  193. OutputImages[0].fillCircle(f.TipPoint.IntX, f.TipPoint.IntY, 4, Constants.FingerTipColor);
  194. }
  195. foreach (TrackedFinger tf in fingerTracker.TrackedObjects)
  196. {
  197. if (tf.CurrentState == TrackingState.Tracked)
  198. {
  199. OutputImages[0].fillCircle(tf.TipPointPrediction.IntX, tf.TipPointPrediction.IntY, 3, Constants.FingerPointsPredictionColor);
  200. OutputImages[0].fillCircle(tf.HandPointPrediction.IntX, tf.HandPointPrediction.IntY, 3, Constants.FingerPointsPredictionColor);
  201. }
  202. }
  203. //image1
  204. OutputImages[1].drawImage(edgeImage.Image.ThresholdBinary(new Gray(0), new Gray(255)), Constants.EdgeImageColor);
  205. foreach (Finger f in fingerTracker.Fingers)
  206. {
  207. for (int i = 0; i < f.SliceTrail.NumSlices; i++)
  208. OutputImages[1].drawLineSegment(f.SliceTrail[i].LineSegment, Constants.FingerSliceColor);
  209. OutputImages[1].drawContour(f.Contour, Constants.FingerContourColor);
  210. OutputImages[1].drawLineSegment(f.LineSegment, Constants.FingerTrackedColor);
  211. OutputImages[1].drawText(f.MidPoint.IntX, f.MidPoint.IntY, f.TrackID.ToString(), Constants.FingerIDColor);
  212. }
  213. //image2
  214. foreach (Hand h in handDetector.Hands)
  215. {
  216. if (h.Side == Hand.HandSide.Right)
  217. OutputImages[2].drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Constants.HandRightColor);
  218. else
  219. OutputImages[2].drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Constants.HandLeftColor);
  220. }
  221. //image3
  222. OutputImages[3].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image.Or(255 - handDetector.HandMask.ThresholdBinary(new Gray(0), new Gray(255))), Constants.DepthImageColor);
  223. foreach (TouchEvent te in touchTracker.TouchEvents)
  224. OutputImages[3].fillCircle(te.Position.IntX, te.Position.IntY, 5, Constants.TouchEventTrackedColor);
  225. if (palmDetector.PalmContour != null && palmDetector.PalmContour.Count<Point>() > 0)
  226. {
  227. OutputImages[3].drawContour(palmDetector.PalmContour, Constants.PalmConturColor);
  228. OutputImages[3].drawPoints(palmDetector.PalmContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE), Constants.PalmConvexHullColor);
  229. }
  230. if (palmDetector.PalmQuad != null)
  231. {
  232. OutputImages[3].fillCircle(palmDetector.ThumbDefectStart.IntX, palmDetector.ThumbDefectStart.IntY, 3, Color.Red);
  233. OutputImages[3].fillCircle(palmDetector.ThumbDefectEnd.IntX, palmDetector.ThumbDefectEnd.IntY, 3, Color.Red);
  234. OutputImages[3].fillCircle(palmDetector.ThumbDefectDepth.IntX, palmDetector.ThumbDefectDepth.IntY, 3, Color.Red);
  235. OutputImages[3].drawLineSegment(new Utility.LineSegment2D(palmDetector.ThumbDefectDepth, (palmDetector.ThumbDefectStart + palmDetector.ThumbDefectEnd) / 2.0f), Constants.PalmThumbDefectColor, 1);
  236. OutputImages[3].drawQuadrangleGrid(palmDetector.PalmQuad, Constants.PalmQuadColor, Constants.PalmGridColor, Constants.PalmGridNumRows, Constants.PalmGridNumColumns);
  237. }
  238. //image4
  239. touchEventVisualizer.updateImage();
  240. OutputImages[4] = touchEventVisualizer.OutputImage;
  241. //borders
  242. for (int i = 0; i < numImages; i++)
  243. {
  244. OutputImages[i].drawRectangle(0, 0, imageWidth - 1, imageHeight - 1, Constants.OutputImageBorderColor);
  245. }
  246. Timer.stop("createOutputImages");
  247. }
  248. }
  249. }