123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220 |
- using BBIWARG.Utility;
- using Emgu.CV;
- using System;
- using System.Collections.Generic;
- using System.Drawing;
- namespace BBIWARG.Recognition.FingerRecognition
- {
- /// <summary>
- /// Each Finger consists of multiple FingerSlices, a FingerSliceTrail is a collection of these slices.
- /// </summary>
- public class FingerSliceTrail
- {
- /// <summary>
- /// the fitted direction through all slice's mid points [end to start]
- /// </summary>
- private Vector2D fittedDirection;
- /// <summary>
- /// indicates whether the variable fittedDirection is up to date (outdates if new slices are added)
- /// </summary>
- private bool fittedDirectionUpToDate;
- /// <summary>
- /// the line segment connection the first slice's mid to the last slice's mid
- /// </summary>
- private LineSegment2D lineSegment;
- /// <summary>
- /// indicates whether the variable lineSegment is up to date (outdates if new start or end slices are added)
- /// </summary>
- private bool lineSegmentUpToDate;
- /// <summary>
- /// the last slice
- /// </summary>
- public FingerSlice EndSlice { get { return Slices[Slices.Count - 1]; } }
- /// <summary>
- /// the fitted direction through all slice's mid points [end to start]
- /// </summary>
- public Vector2D FittedDirection
- {
- get
- {
- if (!fittedDirectionUpToDate)
- updateFittedDirection();
- return fittedDirection;
- }
- }
- /// <summary>
- /// the line segment connecting the start slice's mid to the end slice's mid
- /// </summary>
- public LineSegment2D LineSegment
- {
- get
- {
- if (!lineSegmentUpToDate)
- updateLineSegment();
- return lineSegment;
- }
- }
- /// <summary>
- /// the middle slice
- /// </summary>
- public FingerSlice MidSlice { get { return Slices[NumSlices / 2]; } }
- /// <summary>
- /// the number of slices
- /// </summary>
- public int NumSlices { get { return Slices.Count; } }
- /// <summary>
- /// the finger slices
- /// </summary>
- public List<FingerSlice> Slices { get; private set; }
- /// <summary>
- /// the first slice
- /// </summary>
- public FingerSlice StartSlice { get { return Slices[0]; } }
- /// <summary>
- /// Initializes a new instance of the FingerSliceTrail class.
- /// </summary>
- /// <param name="slice">The initial slice.</param>
- public FingerSliceTrail(FingerSlice slice)
- {
- Slices = new List<FingerSlice>();
- Slices.Capacity = 200;
- addSlice(slice);
- lineSegmentUpToDate = false;
- fittedDirectionUpToDate = false;
- }
- /// <summary>
- /// The slice at the given index.
- /// </summary>
- /// <param name="index">the index</param>
- /// <returns>the slice at the given index</returns>
- public FingerSlice this[int index] { get { return Slices[index]; } }
- /// <summary>
- /// Adds a slice to the end of the slice trail and outdates the lineSegment and fittedDirection.
- /// </summary>
- /// <param name="slice">the slice that should be added</param>
- public void addSlice(FingerSlice slice)
- {
- try
- {
- Slices.Add(slice);
- lineSegmentUpToDate = false;
- fittedDirectionUpToDate = false;
- }
- catch (OutOfMemoryException e) {
- // do nothing...
- }
- }
- /// <summary>
- /// Gets the contour of the finger with a given margin
- /// </summary>
- /// <param name="margin">the margin around the finger (in pixels)</param>
- /// <returns>the contour of the finger</returns>
- public Contour<Point> getContour(float margin)
- {
- List<Point> pointsA = new List<Point>();
- List<Point> pointsB = new List<Point>();
- foreach (FingerSlice slice in Slices)
- {
- Vector2D direction = slice.Direction;
- pointsA.Add(slice.Start + margin * direction.getInverse());
- pointsB.Add(slice.End + margin * direction);
- }
- pointsA.Reverse();
- pointsA.AddRange(pointsB);
- Contour<Point> contour = new Contour<Point>(new MemStorage());
- contour.PushMulti(pointsA.ToArray(), Emgu.CV.CvEnum.BACK_OR_FRONT.FRONT);
- return contour;
- }
- /// <summary>
- /// Calculates the direction of the last few slices.
- /// </summary>
- /// <returns>the end direction (direction towards hand)</returns>
- public Vector2D getEndDirection()
- {
- int innerEndIndex = Math.Max(0, NumSlices - Parameters.FingerNumSlicesForRelativeDirection);
- return (EndSlice.Mid - Slices[innerEndIndex].Mid).normalize();
- }
- /// <summary>
- /// Calculates the direction of the first few slices
- /// </summary>
- /// <returns>the start direction (pointing direction)</returns>
- public Vector2D getStartDirection()
- {
- int innerStartIndex = Math.Min(NumSlices - 1, Parameters.FingerNumSlicesForRelativeDirection);
- return (StartSlice.Mid - Slices[innerStartIndex].Mid).normalize();
- }
- /// <summary>
- /// Removes the first few slices.
- /// </summary>
- /// <param name="numSlices">the number of slices that should be removed</param>
- public void removeFirstSlices(int numSlices)
- {
- Slices.RemoveRange(0, numSlices);
- lineSegmentUpToDate = false;
- fittedDirectionUpToDate = false;
- }
- /// <summary>
- /// Reverses the trail and updates the line segment and the fitted direction
- /// </summary>
- public void reverse()
- {
- Slices.Reverse();
- if (lineSegmentUpToDate)
- lineSegment = new LineSegment2D(lineSegment.P2, lineSegment.P1);
- if (fittedDirectionUpToDate)
- fittedDirection = fittedDirection.getInverse();
- }
- /// <summary>
- /// updates the fitted direction (line fitting through all slices mid points)
- /// </summary>
- private void updateFittedDirection()
- {
- List<PointF> midPoints = new List<PointF>();
- foreach (FingerSlice slice in Slices)
- midPoints.Add(slice.Mid);
- PointF pointOnLine, direction;
- PointCollection.Line2DFitting(midPoints.ToArray(), Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_FAIR, out direction, out pointOnLine);
- fittedDirection = new Vector2D(direction).normalize();
- if (fittedDirection.isInOppositeDirection(LineSegment.Direction))
- fittedDirection = fittedDirection.getInverse();
- fittedDirectionUpToDate = true;
- }
- /// <summary>
- /// updates the line segment (new line segment from end to start)
- /// </summary>
- private void updateLineSegment()
- {
- lineSegment = new LineSegment2D(EndSlice.Mid, StartSlice.Mid);
- lineSegmentUpToDate = true;
- }
- }
- }
|