VideoHandle.cs 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  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 System.Diagnostics;
  8. using bbiwarg.Utility;
  9. using bbiwarg.Recognition.FingerRecognition;
  10. using bbiwarg.Recognition.PalmRecognition;
  11. using bbiwarg.Recognition.TouchRecognition;
  12. using bbiwarg.Recognition.HandRecognition;
  13. using bbiwarg.Images;
  14. using bbiwarg.InputProviders;
  15. using Emgu.CV;
  16. using Emgu.CV.Structure;
  17. using bbiwarg.Graphics;
  18. using TUIO;
  19. namespace bbiwarg
  20. {
  21. class VideoHandle
  22. {
  23. private IInputProvider inputProvider;
  24. private InputFrame inputFrame;
  25. private TuioServer server;
  26. private TuioCursor currentTouchevent;
  27. public int Width { get; private set; }
  28. public int Height { get; private set; }
  29. public int CurrentFrame
  30. {
  31. get
  32. {
  33. if (sourceIsMovie())
  34. return inputProvider.getCurrentMovieFrame();
  35. else
  36. return videoFrame;
  37. }
  38. }
  39. private int lastFrame = int.MaxValue;
  40. public OutputImage[] OutputImages { get; private set; }
  41. private DepthImage depthImage;
  42. private EdgeImage edgeImage;
  43. private ConfidenceImage confidenceImage;
  44. private FingerDetector fingerDetector;
  45. private HandDetector handDetector;
  46. private PalmDetector palmDetector;
  47. private TouchDetector touchDetector;
  48. private PalmTouchDetector palmTouchDetector;
  49. private FingerTracker fingerTracker;
  50. private TouchTracker touchTracker;
  51. private TouchEventVisualizer touchEventVisualizer;
  52. private int videoFrame = 0;
  53. public VideoHandle(IInputProvider inputProvider)
  54. {
  55. this.inputProvider = inputProvider;
  56. }
  57. public void start()
  58. {
  59. palmDetector = new PalmDetector();
  60. server = new TuioServer(Constants.TuioIP, Constants.TuioPort);
  61. inputProvider.init();
  62. inputProvider.start();
  63. inputProvider.updateFrame();
  64. initTrackers();
  65. processFrameUpdate();
  66. }
  67. public void stop()
  68. {
  69. inputProvider.stop();
  70. server.close();
  71. }
  72. public bool sourceIsMovie()
  73. {
  74. return inputProvider.sourceIsMovie();
  75. }
  76. public void reversePlay()
  77. {
  78. inputProvider.reversePlay();
  79. }
  80. public void pauseMovie()
  81. {
  82. inputProvider.pauseMovie();
  83. }
  84. public void unpauseMovie()
  85. {
  86. inputProvider.unpauseMovie();
  87. }
  88. public void nextFrame()
  89. {
  90. if (inputProvider.isActive())
  91. {
  92. inputProvider.releaseFrame();
  93. inputProvider.updateFrame();
  94. processFrameUpdate();
  95. }
  96. else
  97. {
  98. inputProvider.stop();
  99. }
  100. videoFrame++;
  101. }
  102. private void initTrackers() {
  103. touchTracker = new TouchTracker();
  104. fingerTracker = new FingerTracker();
  105. }
  106. private void processFrameUpdate()
  107. {
  108. bool newStarted = (lastFrame - CurrentFrame >= 20);
  109. Timer.start("processFrameUpdate");
  110. if (newStarted) {
  111. //initialize trackers
  112. touchTracker.reset();
  113. fingerTracker.reset();
  114. }
  115. //read data from inputProvider
  116. Timer.start("readInputData");
  117. inputFrame = inputProvider.getInputFrame();
  118. Width = inputFrame.Width;
  119. Height = inputFrame.Height;
  120. Timer.stop("readInputData");
  121. //create output images
  122. Timer.start("createOutputImages");
  123. OutputImages = new OutputImage[Constants.OutputNumImages];
  124. for (int i = 0; i < Constants.OutputNumImages; i++) {
  125. OutputImages[i] = new OutputImage(Width, Height);
  126. }
  127. Timer.stop("createOutputImages");
  128. //create confidenceImage
  129. Timer.start("createConfidenceImage");
  130. Image<Gray, Int16> rawConfidenceImage = new Image<Gray, Int16>(Width, Height, Width * 2, inputFrame.RawConfidenceData);
  131. confidenceImage = new ConfidenceImage(rawConfidenceImage);
  132. Timer.stop("createConfidenceImage");
  133. //create depthImage
  134. Timer.start("createDepthImage");
  135. Image<Gray, Int16> rawDepthImage = new Image<Gray, Int16>(Width, Height, Width * 2, inputFrame.RawDepthData);
  136. rawDepthImage = rawDepthImage.Or((1 - confidenceImage.Mask).Convert<Gray, Int16>().Mul(Int16.MaxValue));
  137. depthImage = new DepthImage(rawDepthImage);
  138. OutputImages[0].Image[0] = OutputImages[0].Image[1] = OutputImages[0].Image[2] = (depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image;
  139. Timer.stop("createDepthImage");
  140. // create edge image
  141. Timer.start("createEdgeImage");
  142. edgeImage = new EdgeImage(depthImage);
  143. OutputImages[1].Image[2] = edgeImage.Image.Mul(255);
  144. Timer.stop("createEdgeImage");
  145. //detect fingers
  146. Timer.start("fingerDetection");
  147. fingerDetector = new FingerDetector(depthImage, edgeImage, OutputImages[1]);
  148. Timer.stop("fingerDetection");
  149. //track fingers
  150. Timer.start("fingerTracking");
  151. fingerTracker.updateTrackedFingers(fingerDetector.Fingers, OutputImages[1]);
  152. Timer.stop("fingerTracking");
  153. //detect hands
  154. Timer.start("handDetection");
  155. handDetector = new HandDetector(depthImage, edgeImage, fingerDetector.Fingers, OutputImages[2]);
  156. Timer.stop("handDetection");
  157. //remove background noise
  158. Timer.start("removeBackground");
  159. OutputImages[3].Image[0] = OutputImages[3].Image[1] = OutputImages[3].Image[2] = (depthImage.MaxDepth - depthImage.MinDepth) - depthImage.Image.Or(255-handDetector.HandMask);
  160. Timer.stop("removeBackground");
  161. //detect palm
  162. Timer.start("palmDetection");
  163. if (newStarted)
  164. palmDetector.reset();
  165. palmDetector.findPalmQuad(OutputImages[3], handDetector.Hands);
  166. Timer.stop("palmDetection");
  167. //detect touchEvents
  168. Timer.start("touchDetection");
  169. touchDetector = new TouchDetector(fingerTracker.Fingers, depthImage, OutputImages[0]);
  170. if (palmDetector.PalmQuad != null)
  171. palmTouchDetector = new PalmTouchDetector(touchDetector.TouchEvents, palmDetector.PalmQuad, palmDetector.PalmHandSide);
  172. Timer.stop("touchDetection");
  173. //track touchEvents
  174. Timer.start("touchTracking");
  175. touchTracker.setDetectedTouchEventsThisFrame(touchDetector.TouchEvents, OutputImages[3]);
  176. Timer.stop("touchTracking");
  177. Timer.start("sending touchEvents");
  178. //send touchevent
  179. if (palmTouchDetector != null)
  180. {
  181. server.initFrame();
  182. if (palmTouchDetector.PalmTouchEvents.Count == 1)
  183. {
  184. PalmTouchEvent touchEvent = palmTouchDetector.PalmTouchEvents[0];
  185. if (currentTouchevent == null)
  186. currentTouchevent = server.addTuioCursor(touchEvent.RelativePalmPosition.X, touchEvent.RelativePalmPosition.Y);
  187. else
  188. server.updateTuioCursor(currentTouchevent, touchEvent.RelativePalmPosition.X, touchEvent.RelativePalmPosition.Y);
  189. }
  190. else if (currentTouchevent != null)
  191. {
  192. server.removeTuioCursor(currentTouchevent);
  193. currentTouchevent = null;
  194. }
  195. server.commitFrame();
  196. }
  197. Timer.stop("sending touchEvents");
  198. // touch event visualizer
  199. if (touchEventVisualizer == null)
  200. touchEventVisualizer = new TouchEventVisualizer(Width, Height);
  201. if (newStarted)
  202. touchEventVisualizer.Reset();
  203. if (palmTouchDetector != null)
  204. {
  205. foreach (PalmTouchEvent e in palmTouchDetector.PalmTouchEvents)
  206. {
  207. touchEventVisualizer.addPalmTouchEvent(e, CurrentFrame);
  208. }
  209. touchEventVisualizer.updateImage();
  210. OutputImages[4] = touchEventVisualizer.OutputImage;
  211. }
  212. // add borders
  213. for (int i = 0; i < Constants.OutputNumImages; i++)
  214. {
  215. OutputImages[i].drawRectangle(0, 0, Width - 1, Height - 1, Color.White);
  216. }
  217. Timer.stop("processFrameUpdate");
  218. lastFrame = CurrentFrame;
  219. }
  220. }
  221. }