|
@@ -15,13 +15,35 @@ using bbiwarg.Input.InputHandling;
|
|
|
|
|
|
namespace bbiwarg.Recognition.TouchRecognition
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// Detects touches by flood filling around a small area around each finger tip and counting the number of affected pixels. If the finger is touching or slightly hovering above something, the flood fill spreads into the touched object and the number of affected pixels is higher.
|
|
|
+ /// </summary>
|
|
|
class TouchDetector
|
|
|
{
|
|
|
+ /// <summary>
|
|
|
+ /// the depth image of the current frame
|
|
|
+ /// </summary>
|
|
|
private DepthImage depthImage;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// the fingers of the current frame
|
|
|
+ /// </summary>
|
|
|
private List<Finger> fingers;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// the palms of the current frame
|
|
|
+ /// </summary>
|
|
|
private List<Palm> palms;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// the detected touches in the current frame
|
|
|
+ /// </summary>
|
|
|
private List<Touch> touches;
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Detects touches in the current frame and stores them in frameData.detectedTouchEvents
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="frameData">the current frame</param>
|
|
|
public void detectTouches(FrameData frameData)
|
|
|
{
|
|
|
depthImage = frameData.DepthImage;
|
|
@@ -30,40 +52,56 @@ namespace bbiwarg.Recognition.TouchRecognition
|
|
|
touches = new List<Touch>();
|
|
|
|
|
|
if (palms.Count > 0)
|
|
|
- detectTouch();
|
|
|
+ {
|
|
|
+ foreach (Finger finger in fingers)
|
|
|
+ {
|
|
|
+ Touch touch = detectTouch(finger);
|
|
|
+ if (touch != null)
|
|
|
+ touches.Add(touch);
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
frameData.DetectedTouches = touches;
|
|
|
}
|
|
|
|
|
|
- private void detectTouch()
|
|
|
+ /// <summary>
|
|
|
+ /// Detects if a finger is touching a palm and either returns a new Touch or null
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="finger">the fingers</param>
|
|
|
+ /// <returns>a new Touch or null</returns>
|
|
|
+ private Touch detectTouch(Finger finger)
|
|
|
{
|
|
|
- foreach (Finger finger in fingers)
|
|
|
- {
|
|
|
- Vector2D tipPoint = finger.TipPoint;
|
|
|
- Vector2D direction = finger.Direction;
|
|
|
- Vector2D tipPointInside = tipPoint.moveWithinBound(depthImage.Size, direction.getInverse(), Parameters.TouchTipInsideFactor);
|
|
|
- Vector2D tipPointOutside = tipPoint.moveWithinBound(depthImage.Size, direction, Parameters.TouchTipOutsideFactor);
|
|
|
+ Vector2D tipPoint = finger.TipPoint;
|
|
|
+ Vector2D direction = finger.Direction;
|
|
|
+ Vector2D tipPointInside = tipPoint.moveWithinBound(depthImage.Size, direction.getInverse(), Parameters.TouchTipInsideFactor);
|
|
|
+ Vector2D tipPointOutside = tipPoint.moveWithinBound(depthImage.Size, direction, Parameters.TouchTipOutsideFactor);
|
|
|
|
|
|
- foreach (Palm palm in palms)
|
|
|
+ foreach (Palm palm in palms)
|
|
|
+ {
|
|
|
+ if (palm.isInside(tipPointOutside))
|
|
|
{
|
|
|
- if (palm.isInside(tipPointOutside))
|
|
|
- {
|
|
|
- Image<Gray, byte> touchMask = getTouchMask(tipPointInside);
|
|
|
+ Image<Gray, byte> touchMask = getTouchMask(tipPointInside);
|
|
|
|
|
|
- int touchPixels = touchMask.CountNonzero()[0];
|
|
|
- int numPixels = touchMask.Width * touchMask.Height;
|
|
|
- float touchValue = touchPixels / (float)numPixels;
|
|
|
+ int touchPixels = touchMask.CountNonzero()[0];
|
|
|
+ int numPixels = touchMask.Width * touchMask.Height;
|
|
|
+ float touchValue = touchPixels / (float)numPixels;
|
|
|
|
|
|
- if (touchValue > Parameters.TouchMinTouchValue)
|
|
|
- {
|
|
|
- Touch touchEvent = new Touch(tipPointOutside, finger, palm);
|
|
|
- touches.Add(touchEvent);
|
|
|
- }
|
|
|
+ if (touchValue > Parameters.TouchMinTouchValue)
|
|
|
+ {
|
|
|
+ Touch touch = new Touch(tipPointOutside, finger, palm);
|
|
|
+ return touch;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ return null;
|
|
|
}
|
|
|
|
|
|
+ /// <summary>
|
|
|
+ /// Gets an image of a small area around the desired touch point (copied from the depth image)
|
|
|
+ /// </summary>
|
|
|
+ /// <param name="touchPoint">the touch position</param>
|
|
|
+ /// <returns>image of the touch area around the touch position</returns>
|
|
|
private Image<Gray, byte> getTouchMask(Vector2D touchPoint)
|
|
|
{
|
|
|
int minX = Math.Max(touchPoint.IntX - 2 * Parameters.TouchAreaSize / 3, 0);
|