/// <summary> /// A point multipy with a double value /// </summary> /// <param name="point1"></param> /// <param name="value"></param> /// <returns></returns> public static Point2D operator *(Point2D point1, double value) { Point2D ret = new Point2D(); ret.X = (int)(point1.X * value); ret.Y = (int)(point1.Y * value); return ret; }
/// <summary> /// Add two point /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <returns></returns> public static Point2D operator +(Point2D point1, Point2D point2) { Point2D ret = new Point2D(); ret.X = point1.X + point2.X; ret.Y = point1.Y + point2.Y; return ret; }
/// <summary> /// Get the vector length from point1 to point(0,0) /// </summary> /// <param name="point1"></param> /// <returns></returns> public static float Length(Point2D point1) { return (float)(Math.Sqrt(point1.X * point1.X + point1.Y * point1.Y)); }
public Point2D(Point2D point) { this.X = point.X; this.Y = point.Y; }
/// <summary> /// get angle between two vectors /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <returns>radian discription for the return angle</returns> public static float Angle(Point2D point1, Point2D point2) { return (float)Math.Acos((point1.X * point2.X + point1.Y * point2.Y) / (Length(point1) * Length(point2))); }
/// <summary> /// Get the Euclidean Distance between two point in 2D space /// </summary> /// <param name="point1"></param> /// <param name="point2"></param> /// <returns></returns> public static float EuclideanDistance(Point2D point1,Point2D point2) { return (float)Math.Sqrt((point1.X - point2.X) * (point1.X - point2.X) + (point1.Y - point2.Y) * (point1.Y - point2.Y)); }
public void FingerDetect(int dalitionErosionMask = 1) { validMatrix = generateValidMatrix(this.pixelDepth3D, this.kinectPalmDetph, dalitionErosionMask); /** Get interiorPixels and contourPixels **/ contourMatrix = new bool[validMatrix.Length][]; for (int i = 0; i < validMatrix.Length; i++) { contourMatrix[i] = new bool[validMatrix[i].Length]; } for (int i = 0; i < validMatrix.Length; i++) { for (int j = 0; j < validMatrix[i].Length; j++) { if (validMatrix[i][j]) { if (4 == adjacentValidPixelCount(validMatrix, i, j)) { interiorPixels.Add(new Point2D(i, j)); } else { contourMatrix[i][j] = true; contourPixels.Add(new Point2D(i, j)); } } } } if (contourPixels.Count != 0) { contour = TurtleSearch(validMatrix, contourPixels.First()); } if (null != contour) { palm = findPalmCenter(interiorPixels, contour); fingerTips = findFingerTips(contour, palm); } }
public PointDepth3D(Point2D point, short depth) { this.X = point.X; this.Y = point.Y; this.Depth = depth; }
/// <summary> /// Turtle Search Algorithm, generate contour list in order /// </summary> /// <param name="valid">validMatrix[][]</param> /// <param name="start">start from any Point2D in contour List</param> /// <returns>contour pixels in order</returns> private List<Point2D> TurtleSearch(bool[][] valid, Point2D start) { List<Point2D> orderContour = new List<Point2D>(); Point2D pre = new Point2D(-1, -1); Point2D curr = new Point2D(start); int dir = 0; do { if (valid[curr.X][curr.Y]) { dir = (dir + 1) % 4; if (curr != pre) { orderContour.Add(new Point2D(curr)); pre = new Point2D(curr); } } else { dir = (dir + 4 - 1) % 4; } switch (dir) { case 0: curr.X += 1; break; //Down case 1: curr.Y += 1; break; //Right case 2: curr.X -= 1; break; //Up case 3: curr.Y -= 1; break; //Left } } while (curr != start); return orderContour; }
/// <summary> /// Map Point2D to PointDepth3D /// </summary> /// <param name="point"></param> /// <returns></returns> private PointDepth3D Point2DMapToDepth3D(Point2D point) { return pixelDepth3D[point.Y * rectWidth + point.X]; }
/// <summary> /// find Palm Center using data in two List: handPixels[] and contourPixels[] /// Discription: Traveral every point in handPixels list, /// caculate the Mininal Euclidean Distance between every point in contourPixels list /// find the maximize distance in the mininal distances set /// </summary> /// <param name="handPixels"></param> /// <param name="contourPixels"></param> /// <returns>Point2D palm</returns> private Point2D findPalmCenter(List<Point2D> interiorPixels, List<Point2D> contourPixels) { Point2D palm = new Point2D(); float min, minMax, distance = 0.0f; minMax = float.MinValue; for (int i = 0; i < interiorPixels.Count; i += 8) { min = float.MaxValue; for (int j = 0; j < contourPixels.Count; j += 2) { distance = Point2D.EuclideanDistance(interiorPixels[i], contourPixels[j]); if (distance < min) { min = distance; } if (min < minMax) break; } if (min > minMax && min != float.MinValue) { minMax = min; palm = interiorPixels[i]; } } return palm; }
/// <summary> /// find fingertips by K_curvature Algorithm /// </summary> /// <param name="contour"></param> /// <param name="palm"></param> /// <returns></returns> private List<Point2D> findFingerTips(List<Point2D> contour, Point2D palm) { List<Point2D> fingerTips = new List<Point2D>(); Point2D p1, p2, p3, pMid, v1, v2; double angle; int size = contour.Count; int fingerJump = 2; float fingerJumpPec = 0.1f; int k = 22; //Debug i < size ---> i < size - k //ignore the last k candinate points for (int i = 0; i < size - k; i += fingerJump) { if (i - k + size < 0) //Need to modify break; p1 = contour[(i - k + size) % size]; p2 = contour[i]; p3 = contour[(i + k + size) % size]; v1 = p1 - p2; v2 = p3 - p2; angle = Point2D.Angle(v1, v2); if (angle > 0 && angle < 40 * (Math.PI / 180)) { pMid = (p1 + p3) * 0.5; if (Point2D.EuclideanDistance(pMid, palm) > Point2D.EuclideanDistance(contour[i], palm)) continue; else { fingerTips.Add(new Point2D(contour[i])); i += (int)(fingerJumpPec * size); } } } //Console.WriteLine(fingerTips.Count); return fingerTips; }
/// <summary> /// Map Point2D to PointDepth3D /// </summary> /// <param name="point"></param> /// <returns></returns> private PointDepth3D Point2DMapToDepth3D(Point2D point) { return(pixelDepth3D[point.Y * rectWidth + point.X]); }