// returns 5 local max points (1 for each fingertip) and 4 local min points (spaces between fingers) public bool FindFingerPoints(List <Point> path, Point centroid, out List <APair <int, double> > maximums, out List <APair <int, double> > minimums) { // find distances to centroid for each path point List <double> distances = new List <double>(); for (int i = 0; i < path.Count; ++i) { Point p = path[i]; if (p != null) { double dist = BitMatrix.Distance(p, centroid); distances.Add(dist); } } List <double> blurredDistances = ListBlur(distances); maximums = FindMaximums(blurredDistances); if (maximums.Count != MAX_COUNT) { minimums = new List <APair <int, double> >(); return(false); } minimums = FindMinimums(blurredDistances, maximums); if (minimums.Count != MIN_COUNT) { return(false); } return(true); }
// calculates distances between max/min points and surface areas for each finger public List <double> FindFingerFeatures(BitMatrix bm, List <Point> path, Point centroid, List <APair <int, double> > maximums, List <APair <int, double> > minimums) { // get finger/hole points List <Point> fingers = new List <Point>(); for (int i = 0; i < maximums.Count; ++i) { fingers.Add(path[maximums[i].First]); } List <Point> holes = new List <Point>(); for (int i = 0; i < minimums.Count; ++i) { holes.Add(path[minimums[i].First]); } List <double> features = new List <double> { // first add left side distances BitMatrix.Distance(fingers[0], holes[0]), BitMatrix.Distance(fingers[1], holes[1]), BitMatrix.Distance(fingers[2], holes[2]), BitMatrix.Distance(fingers[3], holes[3]), // then add right side distances BitMatrix.Distance(fingers[1], holes[0]), BitMatrix.Distance(fingers[2], holes[1]), BitMatrix.Distance(fingers[3], holes[2]), BitMatrix.Distance(fingers[4], holes[3]) }; // now find points before and after first hole to calculate surface areas int preI = maximums[0].First * 2 - minimums[0].First; if (preI < 0) { preI = 0; } else if (preI > path.Count - 1) { preI = path.Count - 1; } Point preHole = path[preI]; Point postHole; // find point before first hole while (preI >= 1 && BitMatrix.Distance(preHole, fingers[0]) < BitMatrix.Distance(fingers[0], holes[0])) { preHole = path[--preI]; } while (preI < path.Count - 2 && BitMatrix.Distance(preHole, fingers[0]) > BitMatrix.Distance(fingers[0], holes[0])) { preHole = path[++preI]; } // find point after last hole int maxId = MAX_COUNT - 1; int minId = MIN_COUNT - 1; int postI = maximums[maxId].First * 2 - minimums[minId].First; if (postI < 0) { postI = 0; } else if (postI > path.Count - 1) { postI = path.Count - 1; } postHole = path[postI]; while (postI < path.Count - 2 && BitMatrix.Distance(postHole, fingers[maxId]) < BitMatrix.Distance(fingers[maxId], holes[minId])) { postHole = path[++postI]; } while (postI >= 1 && BitMatrix.Distance(postHole, fingers[maxId]) > BitMatrix.Distance(fingers[maxId], holes[minId])) { postHole = path[--postI]; } BitMatrix fbm = new BitMatrix(bm); fbm.FillArea(centroid); // #TODO LS generate surface area data //features.Add(Math.Sqrt(bm.GetSurface(fbm, preHole, holes[0]))); //features.Add(Math.Sqrt(bm.GetSurface(fbm, holes[0], holes[1]))); //features.Add(Math.Sqrt(bm.GetSurface(fbm, holes[1], holes[2]))); //features.Add(Math.Sqrt(bm.GetSurface(fbm, holes[2], holes[3]))); //features.Add(Math.Sqrt(bm.GetSurface(fbm, holes[3], postHole))); return(features); }