GlassesWindow.cs 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269
  1. using BBIWARG.Input.InputHandling;
  2. using BBIWARG.Input.InputProviding;
  3. using BBIWARG.Recognition.FingerRecognition;
  4. using BBIWARG.Recognition.PalmRecognition;
  5. using BBIWARG.Utility;
  6. using System;
  7. using System.ComponentModel;
  8. using System.Drawing;
  9. using System.Windows.Forms;
  10. namespace BBIWARG.Output.GlassesOutput
  11. {
  12. /// <summary>
  13. /// A Windows Form which displays a full screen window to be shown on augmented reality glasses.
  14. /// </summary>
  15. public partial class GlassesWindow : Form
  16. {
  17. /// <summary>
  18. /// true iff the calibration image has the latest data
  19. /// </summary>
  20. private bool calibrationImageUpToDate;
  21. /// <summary>
  22. /// position of the current calibration point in the output plane
  23. /// </summary>
  24. private Vector2D currentCalibrationPoint;
  25. /// <summary>
  26. /// id of the current frame
  27. /// </summary>
  28. private int currentFrameID;
  29. /// <summary>
  30. /// true iff the window is showing the latest data
  31. /// </summary>
  32. private bool guiUpToDate;
  33. /// <summary>
  34. /// the image shown on the glasses
  35. /// </summary>
  36. private OutputImage image;
  37. /// <summary>
  38. /// the input handler
  39. /// </summary>
  40. private InputHandler inputHandler;
  41. /// <summary>
  42. /// the input provider
  43. /// </summary>
  44. private IInputProvider inputProvider;
  45. /// <summary>
  46. /// size of the input images
  47. /// </summary>
  48. private ImageSize inputSize;
  49. /// <summary>
  50. /// size of the image show on the glasses
  51. /// </summary>
  52. private ImageSize outputSize;
  53. /// <summary>
  54. /// projection from the input image plane to a plane which lies in front of the wearer of the glasses (output plane)
  55. /// </summary>
  56. private Projection2DTo2D projection;
  57. /// <summary>
  58. /// random number generator
  59. /// </summary>
  60. private Random rand;
  61. /// <summary>
  62. /// timer to periodically update the window
  63. /// </summary>
  64. private System.Windows.Forms.Timer timer;
  65. /// <summary>
  66. /// Creates a GlassesWindow.
  67. /// </summary>
  68. /// <param name="inputProvider">input provider</param>
  69. /// <param name="inputHandler">input handler</param>
  70. /// <param name="name">title of the window</param>
  71. /// <param name="screen">the screen this window is shown on</param>
  72. /// <param name="updateInterval">the update interval for the window in milliseconds</param>
  73. public GlassesWindow(IInputProvider inputProvider, InputHandler inputHandler, String name, Screen screen, int updateInterval)
  74. {
  75. InitializeComponent();
  76. this.inputProvider = inputProvider;
  77. this.inputHandler = inputHandler;
  78. this.inputSize = inputHandler.ImageSize;
  79. this.outputSize = new ImageSize(screen.Bounds.Width, screen.Bounds.Height);
  80. guiUpToDate = false;
  81. calibrationImageUpToDate = false;
  82. rand = new Random();
  83. currentCalibrationPoint = getRandomOutputPoint();
  84. projection = new Projection2DTo2D(inputSize, outputSize, Parameters.GlassesWindowNumCalibrationPoints);
  85. Name = name;
  86. Text = name;
  87. timer = new System.Windows.Forms.Timer();
  88. timer.Interval = updateInterval;
  89. timer.Tick += update;
  90. timer.Start();
  91. KeyPreview = true;
  92. // fullscreen
  93. FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
  94. Location = screen.Bounds.Location;
  95. Size = screen.Bounds.Size;
  96. }
  97. /// <summary>
  98. /// Stops the input provider when closing the window.
  99. /// </summary>
  100. /// <param name="e">event arguments</param>
  101. protected override void OnClosing(CancelEventArgs e)
  102. {
  103. base.OnClosing(e);
  104. inputProvider.stop();
  105. }
  106. /// <summary>
  107. /// Returns a random point in the glasses image.
  108. /// </summary>
  109. /// <returns>a random point in the output image</returns>
  110. private Vector2D getRandomOutputPoint()
  111. {
  112. return outputSize.getAbsolutePoint(new Vector2D((float)rand.NextDouble(), (float)rand.NextDouble()));
  113. }
  114. /// <summary>
  115. /// Handle key down events by showing the next point or finishing or resetting the calibration.
  116. /// </summary>
  117. /// <param name="sender">event sender</param>
  118. /// <param name="e">event arguments</param>
  119. private void GlassesWindow_OnKeyDown(object sender, KeyEventArgs e)
  120. {
  121. if (e.KeyCode == Keys.K)
  122. {
  123. FrameData frameData = inputHandler.FrameData;
  124. if (frameData != null)
  125. {
  126. lock (frameData)
  127. {
  128. if (frameData.TrackedFingers.Count == 1)
  129. {
  130. Vector2D pointOutput = currentCalibrationPoint;
  131. Vector2D pointInput = frameData.TrackedFingers[0].TipPoint;
  132. projection.addCalibrationPoints(pointInput, pointOutput);
  133. currentCalibrationPoint = getRandomOutputPoint();
  134. }
  135. }
  136. }
  137. }
  138. else if (e.KeyCode == Keys.R)
  139. {
  140. projection.reset();
  141. currentCalibrationPoint = getRandomOutputPoint();
  142. }
  143. }
  144. /// <summary>
  145. /// Updates the window.
  146. /// </summary>
  147. /// <param name="sender">the event sender</param>
  148. /// <param name="e">the event arguments</param>
  149. private void update(object sender, EventArgs e)
  150. {
  151. Utility.Timer.start("GlassesWindow.update");
  152. if (!inputProvider.IsActive)
  153. Close();
  154. if (projection.IsCalibrated)
  155. {
  156. FrameData frameData = inputHandler.FrameData;
  157. if (frameData != null)
  158. {
  159. lock (frameData)
  160. {
  161. if (currentFrameID != frameData.FrameID)
  162. {
  163. currentFrameID = frameData.FrameID;
  164. Utility.Timer.start("GlassesWindow.update::updateImage");
  165. updateImage(frameData);
  166. Utility.Timer.stop("GlassesWindow.update::updateImage");
  167. }
  168. }
  169. }
  170. }
  171. else
  172. {
  173. if (!calibrationImageUpToDate)
  174. updateCalibrationImage();
  175. }
  176. if (!guiUpToDate)
  177. {
  178. Utility.Timer.start("GlassesWindow.update::updateGUI");
  179. updateGUI();
  180. Utility.Timer.stop("GlassesWindow.update::updateGUI");
  181. }
  182. Utility.Timer.stop("GlassesWindow.update");
  183. }
  184. /// <summary>
  185. /// Updates the calibration image.
  186. /// </summary>
  187. private void updateCalibrationImage()
  188. {
  189. guiUpToDate = false;
  190. if (image != null)
  191. image.Dispose();
  192. image = new OutputImage(outputSize);
  193. image.fillCircle(currentCalibrationPoint, 25, Color.Orange);
  194. }
  195. /// <summary>
  196. /// Updates the GUI elements.
  197. /// </summary>
  198. private void updateGUI()
  199. {
  200. // update image boxes
  201. imageBox.Image = image;
  202. guiUpToDate = true;
  203. }
  204. /// <summary>
  205. /// Updates the glasses image.
  206. /// </summary>
  207. /// <param name="frameData">data for the new frame</param>
  208. private void updateImage(FrameData frameData)
  209. {
  210. guiUpToDate = false;
  211. if (image != null)
  212. image.Dispose();
  213. image = new OutputImage(outputSize);
  214. foreach (Palm palm in frameData.TrackedPalms)
  215. {
  216. Quadrangle quadInput = palm.Quad;
  217. Vector2D a = projection.projectPoint(quadInput.TopLeft);
  218. Vector2D b = projection.projectPoint(quadInput.TopRight);
  219. Vector2D c = projection.projectPoint(quadInput.BottomRight);
  220. Vector2D d = projection.projectPoint(quadInput.BottomLeft);
  221. Quadrangle quadOutput = new Quadrangle(a, b, c, d);
  222. image.drawQuadrangleGrid(quadOutput, Color.Yellow, Color.Orange, 3, 4);
  223. }
  224. foreach (Finger finger in frameData.TrackedFingers)
  225. {
  226. Vector2D tipProjected = projection.projectPoint(finger.TipPoint);
  227. image.fillCircle(tipProjected, 10, Color.Yellow);
  228. }
  229. }
  230. }
  231. }