|
@@ -14,31 +14,41 @@ namespace bbiwarg.Detectors.Fingers
|
|
|
class Finger
|
|
|
{
|
|
|
private List<Vector<int>> fingerPoints;
|
|
|
+ private bool fingerEndPointsUpToDate = false;
|
|
|
private bool lineUpToDate = false;
|
|
|
+ private float length;
|
|
|
+ private Vector<int> tipPoint;
|
|
|
+ private Vector<int> handPoint;
|
|
|
private Vector<float> direction;
|
|
|
private Vector<float> pointOnLine;
|
|
|
private Vector<float> lineEndPoint1;
|
|
|
private Vector<float> lineEndPoint2;
|
|
|
- private Vector<int> tipPoint;
|
|
|
- private Vector<int> handPoint;
|
|
|
- private float length;
|
|
|
-
|
|
|
- public Finger(Vector<int> fingerPoint)
|
|
|
- {
|
|
|
- fingerPoints = new List<Vector<int>>();
|
|
|
- addFingerPoint(fingerPoint);
|
|
|
+
|
|
|
+ public Finger(List<Vector<int>> fingerPoints) {
|
|
|
+ this.fingerPoints = fingerPoints;
|
|
|
}
|
|
|
|
|
|
- public Vector<float> getLineEndPoint1()
|
|
|
- {
|
|
|
- if (!lineUpToDate) updateLine();
|
|
|
- return lineEndPoint1;
|
|
|
+ public float getLength() {
|
|
|
+ if (!fingerEndPointsUpToDate) updateFingerEndPoints();
|
|
|
+ return length;
|
|
|
}
|
|
|
|
|
|
- public Vector<float> getLineEndPoint2()
|
|
|
- {
|
|
|
- if (!lineUpToDate) updateLine();
|
|
|
- return lineEndPoint2;
|
|
|
+ public int getNumFingerPoints() {
|
|
|
+ return fingerPoints.Count;
|
|
|
+ }
|
|
|
+
|
|
|
+ public List<Vector<int>> getFingerPoints() {
|
|
|
+ return fingerPoints;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Vector<int> getTipPoint() {
|
|
|
+ if (!fingerEndPointsUpToDate) updateFingerEndPoints();
|
|
|
+ return tipPoint;
|
|
|
+ }
|
|
|
+
|
|
|
+ public Vector<int> getHandPoint() {
|
|
|
+ if (!fingerEndPointsUpToDate) updateFingerEndPoints();
|
|
|
+ return handPoint;
|
|
|
}
|
|
|
|
|
|
public Vector<float> getDirection()
|
|
@@ -47,40 +57,37 @@ namespace bbiwarg.Detectors.Fingers
|
|
|
return direction;
|
|
|
}
|
|
|
|
|
|
- public Vector<int> getTipPoint()
|
|
|
+ public Vector<float> getLineEndPoint1()
|
|
|
{
|
|
|
if (!lineUpToDate) updateLine();
|
|
|
- return tipPoint;
|
|
|
+ return lineEndPoint1;
|
|
|
}
|
|
|
|
|
|
- public float getLength()
|
|
|
+ public Vector<float> getLineEndPoint2()
|
|
|
{
|
|
|
if (!lineUpToDate) updateLine();
|
|
|
- return length;
|
|
|
+ return lineEndPoint2;
|
|
|
}
|
|
|
|
|
|
- public void addFingerPoint(Vector<int> fingerPoint)
|
|
|
- {
|
|
|
+ public void addFingerPoint(Vector<int> fingerPoint) {
|
|
|
fingerPoints.Add(fingerPoint);
|
|
|
+ fingerEndPointsUpToDate = false;
|
|
|
lineUpToDate = false;
|
|
|
}
|
|
|
|
|
|
- public float getMinDistance(Vector<int> fingerPoint)
|
|
|
- {
|
|
|
- float minDinstance = float.MaxValue;
|
|
|
- foreach (Vector<int> fp in fingerPoints)
|
|
|
- {
|
|
|
- float distance = fingerPoint.subDistance(fp, 2);
|
|
|
- if (distance < minDinstance)
|
|
|
- {
|
|
|
- minDinstance = distance;
|
|
|
- }
|
|
|
+ public bool isWithinDistance(Vector<int> point, float maxDistance) {
|
|
|
+ foreach (Vector<int> fp in fingerPoints) {
|
|
|
+ if (fp.subDistance(point, 2) <= maxDistance)
|
|
|
+ return true;
|
|
|
}
|
|
|
-
|
|
|
- return minDinstance;
|
|
|
+ return false;
|
|
|
}
|
|
|
|
|
|
- public float getSimilarity(Finger compareFinger) {
|
|
|
+ public float getSimilarity(Finger compareFinger)
|
|
|
+ {
|
|
|
+ if (!fingerEndPointsUpToDate) updateFingerEndPoints();
|
|
|
+ if (!lineUpToDate) updateLine();
|
|
|
+
|
|
|
//startDistance
|
|
|
float maxStartDistance = 100;
|
|
|
float xDiffStart = lineEndPoint1.x - compareFinger.getLineEndPoint1().x;
|
|
@@ -101,40 +108,24 @@ namespace bbiwarg.Detectors.Fingers
|
|
|
float lengthCompareDirection = compareFinger.getDirection().norm();
|
|
|
float directionSimilarity = Math.Abs(scalaProduct / (lengthDirection * lengthCompareDirection));
|
|
|
|
|
|
- //Console.WriteLine(Math.Round(directionSimilarity, 2) + "###" + Math.Round(startSimilarity, 2) + "###" + Math.Round(endSimilarity, 2));
|
|
|
-
|
|
|
return (startSimilarity + endSimilarity + directionSimilarity) / 3;
|
|
|
-
|
|
|
- }
|
|
|
|
|
|
- private void updateLine() {
|
|
|
- //update direction+pointonline
|
|
|
- PointF[] pointArray = new PointF[fingerPoints.Count];
|
|
|
- int i = 0;
|
|
|
- foreach (Vector<int> fp in fingerPoints)
|
|
|
- {
|
|
|
- pointArray[i] = new PointF(fp.x, fp.y);
|
|
|
- ++i;
|
|
|
- }
|
|
|
- PointF tempDirection;
|
|
|
- PointF tempPointOnLine;
|
|
|
- PointCollection.Line2DFitting(pointArray, Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_L2, out tempDirection, out tempPointOnLine);
|
|
|
- direction = new Vector<float>(new float[2]{tempDirection.X, tempDirection.Y});
|
|
|
- pointOnLine = new Vector<float>(new float[2] { tempPointOnLine.X, tempPointOnLine.Y });
|
|
|
+ }
|
|
|
|
|
|
+ private void updateFingerEndPoints() {
|
|
|
Vector<int> fp1 = fingerPoints[0];
|
|
|
Vector<int> fp2 = fingerPoints[0];
|
|
|
- length = 0.0f;
|
|
|
+ length = float.MinValue;
|
|
|
+
|
|
|
foreach (Vector<int> fp in fingerPoints) {
|
|
|
- float distanceToFP1 = fp.subDistance(fp1,2);
|
|
|
- float distanceToFP2 = fp.subDistance(fp2,2);
|
|
|
- if (length < distanceToFP1 && distanceToFP1 >= distanceToFP2)
|
|
|
- {
|
|
|
+ float distanceToFP1 = fp.subDistance(fp1, 2);
|
|
|
+ float distanceToFP2 = fp.subDistance(fp2, 2);
|
|
|
+
|
|
|
+ if (distanceToFP1 > length && distanceToFP1 >= distanceToFP2) {
|
|
|
fp2 = fp;
|
|
|
length = distanceToFP1;
|
|
|
}
|
|
|
- else if (length < distanceToFP2 && distanceToFP2 > distanceToFP1)
|
|
|
- {
|
|
|
+ else if (distanceToFP2 > length && distanceToFP2 > distanceToFP1) {
|
|
|
fp1 = fp;
|
|
|
length = distanceToFP2;
|
|
|
}
|
|
@@ -145,33 +136,39 @@ namespace bbiwarg.Detectors.Fingers
|
|
|
tipPoint = fp1;
|
|
|
handPoint = fp2;
|
|
|
}
|
|
|
- else
|
|
|
+ else
|
|
|
{
|
|
|
tipPoint = fp2;
|
|
|
handPoint = fp1;
|
|
|
}
|
|
|
|
|
|
- //update start+end
|
|
|
- lineEndPoint1 = projectToLine(tipPoint);
|
|
|
- lineEndPoint2 = projectToLine(handPoint);
|
|
|
-
|
|
|
- lineUpToDate = true;
|
|
|
+ fingerEndPointsUpToDate = true;
|
|
|
}
|
|
|
|
|
|
- private Vector<float> projectToLine(Vector<int> 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;
|
|
|
+ private void updateLine() {
|
|
|
+
|
|
|
+ if (!fingerEndPointsUpToDate) updateFingerEndPoints();
|
|
|
|
|
|
- float diff_d = (diffx * dx + diffy * dy);
|
|
|
- float d_d = (dx * dx + dy * dy);
|
|
|
- float q = diff_d / d_d;
|
|
|
+ //update direction+pointOnLine
|
|
|
+ PointF[] pointArray = new PointF[fingerPoints.Count];
|
|
|
+ int i = 0;
|
|
|
+ foreach (Vector<int> fp in fingerPoints)
|
|
|
+ {
|
|
|
+ pointArray[i] = new PointF(fp.x, fp.y);
|
|
|
+ ++i;
|
|
|
+ }
|
|
|
+ PointF tempDirection;
|
|
|
+ PointF tempPointOnLine;
|
|
|
+ PointCollection.Line2DFitting(pointArray, Emgu.CV.CvEnum.DIST_TYPE.CV_DIST_L2, out tempDirection, out tempPointOnLine);
|
|
|
+ direction = new Vector<float>(tempDirection.X, tempDirection.Y);
|
|
|
+ pointOnLine = new Vector<float>(tempPointOnLine.X, tempPointOnLine.Y);
|
|
|
|
|
|
- float newX = ox + q * dx;
|
|
|
- float newY = oy + q * dy;
|
|
|
+ //update start+end
|
|
|
+ lineEndPoint1 = Vector<float>.projectToLine(tipPoint, direction, pointOnLine);
|
|
|
+ lineEndPoint2 = Vector<float>.projectToLine(handPoint, direction, pointOnLine);
|
|
|
|
|
|
- return new Vector<float>(new float[2]{newX, newY});
|
|
|
+ lineUpToDate = true;
|
|
|
}
|
|
|
+
|
|
|
}
|
|
|
}
|