FingerSliceTrail.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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. public 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. {
  62. List<Point> pointsA = new List<Point>();
  63. List<Point> pointsB = new List<Point>();
  64. foreach (FingerSlice slice in Slices)
  65. {
  66. Vector2D direction = slice.Direction;
  67. pointsA.Add(slice.Start + margin * direction.getInverse());
  68. pointsB.Add(slice.End + margin * direction);
  69. }
  70. pointsA.Reverse();
  71. pointsA.AddRange(pointsB);
  72. Contour<Point> contour = new Contour<Point>(new MemStorage());
  73. contour.PushMulti(pointsA.ToArray(), Emgu.CV.CvEnum.BACK_OR_FRONT.FRONT);
  74. return contour;
  75. }
  76. private void updateLineSegment()
  77. {
  78. lineSegment = new LineSegment2D(EndSlice.Mid, StartSlice.Mid);
  79. lineSegmentUpToDate = true;
  80. }
  81. private void updateFittedDirection()
  82. {
  83. List<PointF> midPoints = new List<PointF>();
  84. foreach (FingerSlice slice in Slices)
  85. midPoints.Add(slice.Mid);
  86. PointF pointOnLine, direction;
  87. PointCollection.Line2DFitting(midPoints.ToArray(), Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_FAIR, out direction, out pointOnLine);
  88. fittedDirection = new Vector2D(direction).normalize();
  89. if (fittedDirection.isInOppositeDirection(LineSegment.Direction))
  90. fittedDirection = fittedDirection.getInverse();
  91. fittedDirectionUpToDate = true;
  92. }
  93. }
  94. }