using System; using System.Collections.Generic; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using Emgu.CV; using Emgu.CV.Structure; using bbiwarg.Images; namespace bbiwarg.Detectors.Fingers { class Finger { private List fingerPoints; private bool lineUpToDate = false; private PointF direction; private PointF pointOnLine; private PointF lineEndPoint1; private PointF lineEndPoint2; private FingerPoint tipPoint; private FingerPoint handPoint; private float length; public Finger(FingerPoint fingerPoint) { fingerPoints = new List(); addFingerPoint(fingerPoint); } public PointF getLineEndPoint1() { if (!lineUpToDate) updateLine(); return lineEndPoint1; } public PointF getLineEndPoint2() { if (!lineUpToDate) updateLine(); return lineEndPoint2; } public FingerPoint getTipPoint() { if (!lineUpToDate) updateLine(); return tipPoint; } public PointF getDirection() { if (!lineUpToDate) updateLine(); return direction; } public float getLength() { if (!lineUpToDate) updateLine(); return length; } public void addFingerPoint(FingerPoint fingerPoint) { fingerPoints.Add(fingerPoint); lineUpToDate = false; } public float getMinDistance(FingerPoint fingerPoint) { float minDinstance = float.MaxValue; foreach (FingerPoint fp in fingerPoints) { float distance = fp.getDistanceTo(fingerPoint); if (distance < minDinstance) { minDinstance = distance; } } return minDinstance; } public bool isSimilarTo(Finger compareFinger) { PointF center = new PointF((lineEndPoint1.X + lineEndPoint2.X) / 2, (lineEndPoint1.Y + lineEndPoint2.Y) / 2); PointF compareCenter = new PointF((compareFinger.getLineEndPoint1().X+compareFinger.getLineEndPoint2().X)/2, (compareFinger.getLineEndPoint1().Y+compareFinger.getLineEndPoint2().Y)/2); float xDiff = center.X - compareCenter.X; float yDiff = center.Y - compareCenter.Y; float centerDistance = (float)Math.Sqrt(xDiff * xDiff + yDiff * yDiff); float maxCenterDistance = 40; if (centerDistance > maxCenterDistance) return false; return true; } private void updateLine() { //update direction+pointonline PointF[] pointArray = new PointF[fingerPoints.Count]; int i = 0; foreach (FingerPoint fp in fingerPoints) { pointArray[i] = new PointF(fp.getX(), fp.getY()); ++i; } PointCollection.Line2DFitting(pointArray, Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_L2, out direction, out pointOnLine); FingerPoint fp1 = fingerPoints[0]; FingerPoint fp2 = fingerPoints[0]; length = 0.0f; foreach (FingerPoint fp in fingerPoints) { float distanceToFP1 = fp.getDistanceTo(fp1); float distanceToFP2 = fp.getDistanceTo(fp2); if (length < distanceToFP1 && distanceToFP1 >= distanceToFP2) { fp2 = fp; length = distanceToFP1; } else if (length < distanceToFP2 && distanceToFP2 > distanceToFP1) { fp1 = fp; length = distanceToFP2; } } if (fp1.getY() < fp2.getY()) { tipPoint = fp1; handPoint = fp2; } else { tipPoint = fp2; handPoint = fp1; } //update start+end lineEndPoint1 = projectToLine(new PointF(tipPoint.getX(), tipPoint.getY())); lineEndPoint2 = projectToLine(new PointF(handPoint.getX(), handPoint.getY())); lineUpToDate = true; } private PointF projectToLine(PointF p) { float px = p.X, py = p.Y, dx = direction.X, dy = direction.Y, ox = pointOnLine.X, oy = pointOnLine.Y; float diffx = px - ox; float diffy = py - oy; float diff_d = (diffx * dx + diffy * dy); float d_d = (dx * dx + dy * dy); float q = diff_d / d_d; return new PointF(ox + q * dx, oy + q * dy); } } }