VideoHandle.cs 9.1 KB

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