private Mat DetectServing(Mat mat) { mat = mat.ToImage <Bgr, byte>().Rotate(90, new Bgr(0, 0, 0)).Mat; Mat result = mat.Clone(); var processedImage = PreProcessImage(mat); var detectedBall = DetectBall(processedImage); var detectedHand = DetectHand(processedImage); switch (rule) { case InitiateRule.FirstRule: DetectFirstRule(detectedBall, detectedHand, result); break; case InitiateRule.SecondRule: DetectSecondRule(detectedBall, lastFrameBall, lastFrameBallInHand, detectedHand, result); break; default: rule = InitiateRule.FirstRule; break; } /*bool isLegal = DetectFirstRule(detectedBall, detectedHand, result); * if (isLegal) * { * DetectSecondRule(detectedBall, lastFoundBall, lastFrameBallInHand, detectedHand, result); * }*/ result = DrawObjects(detectedBall, detectedHand, mat); lastFrame = mat; lastFrameBall = detectedBall.Center.X != 0 ? detectedBall : lastFrameBall; return(result); }
private void DetectSecondRule(CircleF currentFrameBall, CircleF lastFrameBall, CircleF lastFrameBallInHand, VectorOfPoint hand, Mat image) { // compare last frame ball coordinates with current frame ball coordinates // if y axis is highier in current frame - loop again if (currentFrameBall.Center.Y < lastFrameBall.Center.Y) { //recordedHeight = ((lastFrameBallInHand.Center.Y - currentFrameBall.Center.Y) * 2) / lastFrameBall.Radius; return; } if (currentFrameBall.Center.Y > lastFrameBall.Center.Y && currentFrameBall.Center.Y > lastFrameBallInHand.Center.Y) { rule = InitiateRule.FirstRule; recordedHeight = -1; //recordedHeight = ((lastFrameBallInHand.Center.Y - currentFrameBall.Center.Y) * 2) / lastFrameBall.Radius; return; } // if y axis is highier than when ball was in hand but lower that last frame - calculate height (last frame - last fame in hand if (currentFrameBall.Center.Y > lastFrameBall.Center.Y && currentFrameBall.Center.Y < lastFrameBallInHand.Center.Y) { float height = lastFrameBallInHand.Center.Y - lastFrameBall.Center.Y; if (height >= (lastFrameBall.Radius * 2 * 4)) { line = new LineSegment2D(new System.Drawing.Point( (int)lastFrameBall.Center.X, (int)lastFrameBall.Center.Y), new System.Drawing.Point((int)lastFrameBallInHand.Center.X, (int)lastFrameBallInHand.Center.Y) ); } recordedHeight = (height * 2) / lastFrameBall.Radius; rule = InitiateRule.FirstRule; return; } // if ball is not recognized for 1 second - count as failed pass - go to first rule. // need logging }
private bool DetectFirstRule(CircleF ball, VectorOfPoint detectedHand, Mat image) { Mat circle = new Mat(image.Rows, image.Cols, image.Depth, image.NumberOfChannels); Mat hand = new Mat(image.Rows, image.Cols, image.Depth, image.NumberOfChannels); circle.SetTo(new MCvScalar(0)); hand.SetTo(new MCvScalar(0)); int averageBallRadius = lastHalfSecondRadiuses.Count > 0 ? lastHalfSecondRadiuses.Max() : (int)ball.Radius; if (ball.Radius > 0) { CvInvoke.Circle(circle, System.Drawing.Point.Round(ball.Center), averageBallRadius, new Bgr(System.Drawing.Color.White).MCvScalar, -1); } if (detectedHand.Size != 0) { var cont = new VectorOfVectorOfPoint(detectedHand); VectorOfPoint hull = new VectorOfPoint(); CvInvoke.ConvexHull(detectedHand, hull, false, true); cont = new VectorOfVectorOfPoint(hull); CvInvoke.DrawContours(hand, cont, 0, new Bgr(System.Drawing.Color.White).MCvScalar, -1); } Mat res = new Mat(image.Rows, image.Cols, image.Depth, image.NumberOfChannels); CvInvoke.BitwiseAnd(circle, hand, res); CvInvoke.CvtColor(res, res, ColorConversion.Hsv2Bgr); CvInvoke.CvtColor(res, res, ColorConversion.Bgr2Gray); bool ballInHand = CvInvoke.CountNonZero(res) > 0; /*double isInSideSouth = -1.0; * double isInSideNorth = -1.0; * double isInSideEast = -1.0; * double isInSideWest = -1.0;*/ /*if (detectedHand.Size != 0 && ball.Radius > 0) * { * isInSideSouth = CvInvoke.PointPolygonTest(detectedHand, new PointF(ball.Center.X, ball.Center.Y + ball.Radius), false); * isInSideNorth = CvInvoke.PointPolygonTest(detectedHand, new PointF(ball.Center.X, ball.Center.Y - ball.Radius), false); * isInSideEast = CvInvoke.PointPolygonTest(detectedHand, new PointF(ball.Center.X + ball.Radius, ball.Center.Y), false); * isInSideWest = CvInvoke.PointPolygonTest(detectedHand, new PointF(ball.Center.X - ball.Radius, ball.Center.Y), false); * } * if (isInSideSouth == 1 || isInSideSouth == 0 || isInSideNorth == 1 || isInSideNorth == 0 || isInSideEast == 1 || isInSideEast == 0 || isInSideWest == 1 || isInSideWest == 0) * { * ballInHand = true; * } * else * { * ballInHand = false; * }*/ if (ballInHand == true) { lastFrameBallInHand = ball; } if (ballInHand == false && ballIsInHand == true) { rule = InitiateRule.SecondRule; } ballIsInHand = ballInHand; return(ballInHand); }