|
@@ -16,53 +16,61 @@ namespace bbiwarg.Images
|
|
|
class PalmImage
|
|
|
{
|
|
|
private Image<Gray, Byte> image;
|
|
|
+ private Image<Gray, Byte> output;
|
|
|
private int width, height;
|
|
|
- bool[,] inContour;
|
|
|
|
|
|
- public PalmImage(EdgeImage edgeImage, FingerTracker fingerTracker)
|
|
|
+ public PalmImage(EdgeImage edgeImage, FingerDetector fingerDetector)
|
|
|
{
|
|
|
- image = edgeImage.getImage(); //.Clone();
|
|
|
+ image = edgeImage.getImage().Clone();
|
|
|
width = image.Width;
|
|
|
height = image.Height;
|
|
|
-
|
|
|
- foreach (Finger f in fingerTracker.getFingers())
|
|
|
- {
|
|
|
- Vector<float> tip = new Vector<float>(new float[] { f.Tip.X, f.Tip.Y });
|
|
|
- Vector<float> hand = new Vector<float>(new float[] { f.Hand.X, f.Hand.Y });
|
|
|
|
|
|
+ List<Finger> trackedFingers = fingerDetector.Fingers;
|
|
|
+ Finger leftMost = null;
|
|
|
+ float minX = float.MaxValue;
|
|
|
+ foreach (Finger f in trackedFingers)
|
|
|
+ {
|
|
|
+ float midX = ((f.Hand + f.Tip) / 2).X;
|
|
|
+ if (midX < minX)
|
|
|
+ {
|
|
|
+ minX = midX;
|
|
|
+ leftMost = f;
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
- for (int x = 0; x < width; ++x)
|
|
|
+ Image<Gray, Byte> fingerSliceMask = new Image<Gray, byte>(width, height, new Gray(1));
|
|
|
+ foreach (Finger f in trackedFingers)
|
|
|
+ {
|
|
|
+ if (f != leftMost)
|
|
|
{
|
|
|
- for (int y = 0; y < height; ++y)
|
|
|
+ foreach (FingerSlice s in f.SliceTrail.getSlices())
|
|
|
{
|
|
|
- if (image.Data[y, x, 0] != 0)
|
|
|
+ Vector2D start = s.Start, end = s.End;
|
|
|
+ if ((int)start.Y == (int)end.Y)
|
|
|
{
|
|
|
- Vector<float> p = new Vector<float>(new float[] { x, y });
|
|
|
-
|
|
|
- float l2 = (tip - hand) * (tip - hand);
|
|
|
- float t = (p - tip) * (hand - tip) / l2;
|
|
|
- if (t >= 0.0 && t <= 1.0)
|
|
|
- {
|
|
|
- Vector<float> tmp = hand - tip;
|
|
|
- tmp.multiply(t);
|
|
|
- Vector<float> projection = tip + tmp;
|
|
|
-
|
|
|
- if (p.distance(projection) <= 15)
|
|
|
- image.Data[y, x, 0] = 0;
|
|
|
- }
|
|
|
+ int y = (int)start.Y;
|
|
|
+ for (int x = (int)start.X; x <= (int)end.X; ++x)
|
|
|
+ image.Data[y, x, 0] = 0;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
+ int x = (int)start.X;
|
|
|
+ for (int y = (int)start.Y; y <= (int)end.Y; ++y)
|
|
|
+ image.Data[y, x, 0] = 0;
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ image = image.And(fingerSliceMask.Erode(3));
|
|
|
+
|
|
|
findContour();
|
|
|
}
|
|
|
|
|
|
private void findContour()
|
|
|
{
|
|
|
- //image = image.Dilate(1);
|
|
|
- Contour<Point> contour = image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE,
|
|
|
- Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST);
|
|
|
+ image.Dilate(1);
|
|
|
+ Contour<Point> contour = image.FindContours(Emgu.CV.CvEnum.CHAIN_APPROX_METHOD.CV_CHAIN_APPROX_NONE, Emgu.CV.CvEnum.RETR_TYPE.CV_RETR_LIST);
|
|
|
|
|
|
Contour<Point> maxContour = contour;
|
|
|
double maxPerimeter = 0;
|
|
@@ -76,17 +84,14 @@ namespace bbiwarg.Images
|
|
|
contour = contour.HNext;
|
|
|
}
|
|
|
|
|
|
- inContour = new bool[width, height];
|
|
|
- if (maxContour != null)
|
|
|
- {
|
|
|
- foreach (Point p in maxContour)
|
|
|
- inContour[p.X, p.Y] = true;
|
|
|
- }
|
|
|
+ output = new Image<Gray, byte>(width, height, new Gray(0));
|
|
|
+ output.Draw(maxContour, new Gray(1), 1);
|
|
|
+ output.Draw(maxContour.GetConvexHull(Emgu.CV.CvEnum.ORIENTATION.CV_CLOCKWISE), new Gray(1), 1);
|
|
|
}
|
|
|
|
|
|
public bool belongsToPalm(int x, int y)
|
|
|
{
|
|
|
- return inContour[x, y];
|
|
|
+ return output.Data[y, x, 0] == 1;
|
|
|
}
|
|
|
}
|
|
|
}
|