InputHandler.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  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 HandTracker handTracker;
  39. private PalmTracker palmTracker;
  40. private TouchTracker touchTracker;
  41. private TouchEventVisualizer touchEventVisualizer;
  42. private TuioCommunicator tuioCommunicator;
  43. public InputHandler(InputProvider inputProvider)
  44. {
  45. this.inputProvider = inputProvider;
  46. this.imageWidth = inputProvider.ImageWidth;
  47. this.imageHeight = inputProvider.ImageHeight;
  48. this.currentFrameID = inputProvider.CurrentFrameID;
  49. this.lastFrameID = this.currentFrameID - 1;
  50. initializeConsistentObjects();
  51. }
  52. private void initializeConsistentObjects()
  53. {
  54. fingerTracker = new FingerTracker();
  55. handTracker = new HandTracker();
  56. palmTracker = new PalmTracker();
  57. touchTracker = new TouchTracker();
  58. if (Constants.OutputEnabled)
  59. {
  60. touchEventVisualizer = new TouchEventVisualizer(imageWidth, imageHeight);
  61. //register touchEventVisualizer to touchTracker
  62. touchTracker.TouchDown += touchEventVisualizer.touchDown;
  63. touchTracker.TouchMove += touchEventVisualizer.touchMove;
  64. touchTracker.TouchUp += touchEventVisualizer.touchUp;
  65. }
  66. if (Constants.TuioEnabled)
  67. {
  68. tuioCommunicator = new TuioCommunicator(Constants.TuioIP, Constants.TuioPort);
  69. //register tuiCommunicator to touchTracker
  70. touchTracker.TouchDown += tuioCommunicator.touchDown;
  71. touchTracker.TouchMove += tuioCommunicator.touchMove;
  72. touchTracker.TouchUp += tuioCommunicator.touchUp;
  73. }
  74. }
  75. private void resetConsistentObjects()
  76. {
  77. touchTracker.reset();
  78. handTracker.reset();
  79. palmTracker.reset();
  80. fingerTracker.reset();
  81. if (Constants.OutputEnabled)
  82. touchEventVisualizer.reset();
  83. if (Constants.TuioEnabled)
  84. tuioCommunicator.reset();
  85. }
  86. public void updateFrame()
  87. {
  88. Timer.start("updateFrame");
  89. if (currentFrameID != inputProvider.CurrentFrameID)
  90. {
  91. beforeUpdateFrame();
  92. if (lastFrameID - currentFrameID > 20)
  93. resetConsistentObjects();
  94. createConfidenceImage();
  95. createDepthImage();
  96. createEdgeImage();
  97. detectFingers();
  98. trackFingers();
  99. detectHands();
  100. trackHands();
  101. detectPalm();
  102. trackPalm();
  103. detectTouchEvents();
  104. trackTouchEvents();
  105. afterUpdateFrame();
  106. }
  107. Timer.stop("updateFrame");
  108. }
  109. private void beforeUpdateFrame()
  110. {
  111. Timer.start("beforeUpdateFrame");
  112. currentInputFrame = inputProvider.CurrentFrame;
  113. lastFrameID = currentFrameID;
  114. currentFrameID = currentInputFrame.FrameID;
  115. Logger.CurrentFrame = currentFrameID;
  116. if (Constants.TuioEnabled)
  117. tuioCommunicator.initFrame();
  118. Timer.stop("beforeUpdateFrame");
  119. }
  120. private void afterUpdateFrame()
  121. {
  122. Timer.start("afterUpdateFrame");
  123. if (Constants.TuioEnabled)
  124. tuioCommunicator.commitFrame();
  125. if (Constants.OutputEnabled)
  126. createOutputImages();
  127. Timer.stop("afterUpdateFrame");
  128. }
  129. private void createConfidenceImage()
  130. {
  131. Timer.start("createCnfdncImg");
  132. Image<Gray, Int16> rawConfidenceImage = new Image<Gray, Int16>(imageWidth, imageHeight, imageWidth * 2, currentInputFrame.RawConfidenceData);
  133. confidenceImage = new ConfidenceImage(rawConfidenceImage);
  134. Timer.stop("createCnfdncImg");
  135. }
  136. private void createDepthImage()
  137. {
  138. Timer.start("createDepthImage");
  139. Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(imageWidth, imageHeight, imageWidth * 2, currentInputFrame.RawDepthData);
  140. rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));
  141. depthImage = new DepthImage(rawDepthImage);
  142. Timer.stop("createDepthImage");
  143. }
  144. private void createEdgeImage()
  145. {
  146. Timer.start("createEdgeImage");
  147. edgeImage = new EdgeImage(depthImage);
  148. Timer.stop("createEdgeImage");
  149. }
  150. private void detectFingers()
  151. {
  152. Timer.start("detectFingers");
  153. fingerDetector = new FingerDetector(depthImage, edgeImage);
  154. Timer.stop("detectFingers");
  155. }
  156. private void trackFingers()
  157. {
  158. Timer.start("trackFingers");
  159. fingerTracker.updateFrame(fingerDetector.Fingers);
  160. Timer.stop("trackFingers");
  161. }
  162. private void detectHands()
  163. {
  164. Timer.start("detectHands");
  165. handDetector = new HandDetector(depthImage, edgeImage, fingerTracker.Fingers);
  166. Timer.stop("detectHands");
  167. }
  168. private void trackHands()
  169. {
  170. Timer.start("trackHands\t");
  171. handTracker.updateFrame(handDetector.Hands);
  172. Timer.stop("trackHands\t");
  173. }
  174. private void detectPalm()
  175. {
  176. Timer.start("detectPalm\t");
  177. palmDetector = new PalmDetector(handTracker.Hands);
  178. Timer.stop("detectPalm\t");
  179. }
  180. private void trackPalm()
  181. {
  182. Timer.start("trackPalm\t");
  183. palmTracker.updateFrame(palmDetector.Palms);
  184. Timer.stop("trackPalm\t");
  185. }
  186. private void detectTouchEvents()
  187. {
  188. Timer.start("detectTouchEvents");
  189. touchDetector = new TouchDetector(depthImage, fingerTracker.Fingers, palmTracker.OptimizedPalms);
  190. Timer.stop("detectTouchEvents");
  191. }
  192. private void trackTouchEvents()
  193. {
  194. Timer.start("trackTouchEvents");
  195. touchTracker.updateFrame(touchDetector.TouchEvents);
  196. Timer.stop("trackTouchEvents");
  197. }
  198. private void createOutputImages()
  199. {
  200. Timer.start("createOutputImages");
  201. int numImages = Constants.OutputNumImages;
  202. OutputImages = new OutputImage[numImages];
  203. for (int i = 0; i < numImages; i++)
  204. {
  205. OutputImages[i] = new OutputImage(imageWidth, imageHeight);
  206. }
  207. //image0
  208. OutputImages[0].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image, Constants.DepthImageColor);
  209. foreach (Finger f in fingerTracker.Fingers)
  210. {
  211. OutputImages[0].fillCircle(f.TipPoint.IntX, f.TipPoint.IntY, 4, Constants.FingerTipColor);
  212. }
  213. foreach (TrackedFinger tf in fingerTracker.TrackedObjects)
  214. {
  215. if (tf.CurrentState == TrackingState.Tracked)
  216. {
  217. OutputImages[0].fillCircle(tf.TipPointPrediction.IntX, tf.TipPointPrediction.IntY, 3, Constants.FingerPointsPredictionColor);
  218. OutputImages[0].fillCircle(tf.HandPointPrediction.IntX, tf.HandPointPrediction.IntY, 3, Constants.FingerPointsPredictionColor);
  219. }
  220. }
  221. //image1
  222. OutputImages[1].drawImage(edgeImage.Image.ThresholdBinary(new Gray(0), new Gray(255)), Constants.EdgeImageColor);
  223. foreach (Finger f in fingerTracker.Fingers)
  224. {
  225. for (int i = 0; i < f.SliceTrail.NumSlices; i++)
  226. OutputImages[1].drawLineSegment(f.SliceTrail[i].LineSegment, Constants.FingerSliceColor);
  227. OutputImages[1].drawContour(f.Contour, Constants.FingerContourColor);
  228. OutputImages[1].drawLineSegment(f.LineSegment, Constants.FingerTrackedColor);
  229. OutputImages[1].drawText(f.MidPoint.IntX, f.MidPoint.IntY, f.TrackID.ToString(), Constants.FingerIDColor);
  230. }
  231. //image2
  232. foreach (Hand h in handTracker.Hands)
  233. {
  234. OutputImages[2].drawImage(h.Mask.ThresholdBinary(new Gray(0), new Gray(255)), Constants.HandColor[h.ZIndex % Constants.HandNumColors]);
  235. OutputImages[2].fillCircle(h.Centroid.IntX, h.Centroid.IntY, 5, Constants.HandCentroidColor);
  236. OutputImages[2].drawText(h.Centroid.IntX, h.Centroid.IntY, h.TrackID.ToString(), Constants.HandIDColor);
  237. if (h.ThumbDefect != null)
  238. {
  239. OutputImages[2].fillCircle(h.ThumbDefect.Inner.IntX, h.ThumbDefect.Inner.IntY, 4, Color.CornflowerBlue);
  240. OutputImages[2].fillCircle(h.ThumbDefect.OuterShort.IntX, h.ThumbDefect.OuterShort.IntY, 4, Color.CornflowerBlue);
  241. OutputImages[2].fillCircle(h.ThumbDefect.OuterLong.IntX, h.ThumbDefect.OuterLong.IntY, 4, Color.CornflowerBlue);
  242. }
  243. }
  244. //image3
  245. OutputImages[3].drawImage((depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image.Or(255 - handDetector.HandMask.ThresholdBinary(new Gray(0), new Gray(255))), Constants.DepthImageColor);
  246. foreach (TouchEvent te in touchTracker.TouchEvents)
  247. OutputImages[3].fillCircle(te.Position.IntX, te.Position.IntY, 5, Constants.TouchEventTrackedColor);
  248. foreach (Palm p in palmTracker.OptimizedPalms) {
  249. OutputImages[3].drawQuadrangleGrid(p.Quad, Constants.PalmQuadColor, Constants.PalmGridColor, Constants.PalmGridNumRows, Constants.PalmGridNumColumns);
  250. }
  251. //image4
  252. touchEventVisualizer.updateImage();
  253. OutputImages[4] = touchEventVisualizer.OutputImage;
  254. //borders
  255. for (int i = 0; i < numImages; i++)
  256. {
  257. OutputImages[i].drawRectangle(0, 0, imageWidth - 1, imageHeight - 1, Constants.OutputImageBorderColor);
  258. }
  259. Timer.stop("createOutputImages");
  260. }
  261. }
  262. }