FingerSliceTrail.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 bbiwarg.Utility;
  8. using Emgu.CV;
  9. namespace bbiwarg.Recognition.FingerRecognition
  10. {
  11. class FingerSliceTrail
  12. {
  13. private LineSegment2D lineSegment;
  14. private Vector2D fittedDirection;
  15. private bool lineSegmentUpToDate;
  16. private bool fittedDirectionUpToDate;
  17. public List<FingerSlice> Slices { get; private set; }
  18. public FingerSlice StartSlice { get { return Slices[0]; } }
  19. public FingerSlice MidSlice { get { return Slices[NumSlices / 2]; } }
  20. public FingerSlice EndSlice { get { return Slices[Slices.Count - 1]; } }
  21. public FingerSlice this[int index] { get { return Slices[index]; } }
  22. public int NumSlices { get { return Slices.Count; } }
  23. public LineSegment2D LineSegment { get { if (!lineSegmentUpToDate) updateLineSegment(); return lineSegment; } }
  24. public Vector2D FittedDirection { get { if (!fittedDirectionUpToDate) updateFittedDirection(); return fittedDirection; } }
  25. public FingerSliceTrail(FingerSlice slice)
  26. {
  27. Slices = new List<FingerSlice>();
  28. addSlice(slice);
  29. lineSegmentUpToDate = false;
  30. fittedDirectionUpToDate = false;
  31. }
  32. public void addSlice(FingerSlice slice)
  33. {
  34. Slices.Add(slice);
  35. lineSegmentUpToDate = false;
  36. fittedDirectionUpToDate = false;
  37. }
  38. public Vector2D getStartDirection()
  39. {
  40. int innerStartIndex = Math.Min(NumSlices-1, Parameters.FingerNumSlicesForRelativeDirection);
  41. return (StartSlice.Mid - Slices[innerStartIndex].Mid).normalize();
  42. }
  43. public Vector2D getEndDirection()
  44. {
  45. int innerEndIndex = Math.Max(0, NumSlices - Parameters.FingerNumSlicesForRelativeDirection);
  46. return (EndSlice.Mid - Slices[innerEndIndex].Mid).normalize();
  47. }
  48. public void removeFirstSlices(int numSlices)
  49. {
  50. Slices.RemoveRange(0, numSlices);
  51. lineSegmentUpToDate = false;
  52. fittedDirectionUpToDate = false;
  53. }
  54. public void reverse()
  55. {
  56. Slices.Reverse();
  57. lineSegmentUpToDate = false;
  58. fittedDirectionUpToDate = false;
  59. }
  60. public Contour<Point> getContour(float margin) {
  61. List<Point> pointsA = new List<Point>();
  62. List<Point> pointsB = new List<Point>();
  63. foreach (FingerSlice slice in Slices)
  64. {
  65. Vector2D direction = slice.Direction;
  66. pointsA.Add(slice.Start.moveWithinBound(direction.getInverse(), margin));
  67. pointsB.Add(slice.End.moveWithinBound(direction, margin));
  68. }
  69. pointsA.Reverse();
  70. pointsA.AddRange(pointsB);
  71. Contour<Point> contour = new Contour<Point>(new MemStorage());
  72. contour.PushMulti(pointsA.ToArray(), Emgu.CV.CvEnum.BACK_OR_FRONT.FRONT);
  73. return contour;
  74. }
  75. private void updateLineSegment()
  76. {
  77. lineSegment = new LineSegment2D(EndSlice.Mid, StartSlice.Mid);
  78. lineSegmentUpToDate = true;
  79. }
  80. private void updateFittedDirection()
  81. {
  82. List<PointF> midPoints = new List<PointF>();
  83. foreach (FingerSlice slice in Slices)
  84. midPoints.Add(slice.Mid);
  85. PointF pointOnLine, direction;
  86. PointCollection.Line2DFitting(midPoints.ToArray(), Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_FAIR, out direction, out pointOnLine);
  87. fittedDirection = new Vector2D(direction).normalize();
  88. if (fittedDirection.isInOppositeDirection(LineSegment.Direction))
  89. fittedDirection = fittedDirection.getInverse();
  90. fittedDirectionUpToDate = true;
  91. }
  92. }
  93. }