public DetectedThrow GetThrow() { if (rays.Count < 2) { rays.Clear(); return(null); } var firstBestRay = rays.OrderByDescending(i => i.ContourArea).ElementAt(0); var secondBestRay = rays.OrderByDescending(i => i.ContourArea).ElementAt(1); rays.Clear(); var poi = MeasureService.FindLinesIntersection(firstBestRay.CamPoint, firstBestRay.RayPoint, secondBestRay.CamPoint, secondBestRay.RayPoint); if (float.IsNaN(poi.X) || float.IsNaN(poi.Y)) { return(null); } var thrw = PrepareThrowData(poi, firstBestRay, secondBestRay); return(thrw); }
public DetectedThrow GetThrow() { logger.Debug($"Calculate throw start"); if (rays.Count < 2) { logger.Debug($"Rays count < 2. Calculate throw end."); rays.Clear(); return(null); } rays.ForEach(r => logger.Info($"Ray:'{r}'")); var firstBestRay = rays.OrderByDescending(i => i.ContourArc).ElementAt(0); var secondBestRay = rays.OrderByDescending(i => i.ContourArc).ElementAt(1); rays.Clear(); logger.Info($"Best rays:'{firstBestRay}' and '{secondBestRay}'"); var poi = MeasureService.FindLinesIntersection(firstBestRay.CamPoint, firstBestRay.RayPoint, secondBestRay.CamPoint, secondBestRay.RayPoint); if (float.IsNaN(poi.X) || float.IsNaN(poi.Y)) { logger.Info($"Corrupted poi. Abort"); return(null); } var thrw = PrepareThrowData(poi); drawService.ProjectionDrawLine(firstBestRay.CamPoint, firstBestRay.RayPoint, new Bgr(Color.Aqua).MCvScalar, true); drawService.ProjectionDrawLine(secondBestRay.CamPoint, secondBestRay.RayPoint, new Bgr(Color.Aqua).MCvScalar, false); drawService.ProjectionDrawThrow(poi, false); drawService.PrintThrow(thrw); logger.Info($"Throw:{thrw}"); logger.Debug($"Calculate throw end."); return(thrw); }
private Ray ProcessDartContour(CamService cam, DartContour dartContour) { // Moments and centerpoint // var contourMoments = CvInvoke.Moments(processedContour); // var contourCenterPoint = new PointF((float) (contourMoments.M10 / contourMoments.M00), // (float) camService.roiPosYSlider + (float) (contourMoments.M01 / contourMoments.M00)); // Find contour rectangle var rect = CvInvoke.MinAreaRect(dartContour.ContourPoints); var box = CvInvoke.BoxPoints(rect); var contourBoxPoint1 = new PointF(box[0].X, (float)cam.roiPosYSlider + box[0].Y); var contourBoxPoint2 = new PointF(box[1].X, (float)cam.roiPosYSlider + box[1].Y); var contourBoxPoint3 = new PointF(box[2].X, (float)cam.roiPosYSlider + box[2].Y); var contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y); // Setup vertical contour middlepoints var contourHeight = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2); var contourWidth = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1); PointF contourBoxMiddlePoint1; PointF contourBoxMiddlePoint2; if (contourWidth > contourHeight) { contourBoxMiddlePoint1 = MeasureService.FindMiddle(contourBoxPoint1, contourBoxPoint2); contourBoxMiddlePoint2 = MeasureService.FindMiddle(contourBoxPoint4, contourBoxPoint3); } else { contourBoxMiddlePoint1 = MeasureService.FindMiddle(contourBoxPoint4, contourBoxPoint1); contourBoxMiddlePoint2 = MeasureService.FindMiddle(contourBoxPoint3, contourBoxPoint2); } // Find spikeLine to surface var spikeLinePoint1 = contourBoxMiddlePoint1; var spikeLinePoint2 = contourBoxMiddlePoint2; var spikeLineLength = cam.surfaceSlider - contourBoxMiddlePoint2.Y; var spikeAngle = MeasureService.FindAngle(contourBoxMiddlePoint2, contourBoxMiddlePoint1); spikeLinePoint1.X = (float)(contourBoxMiddlePoint2.X + Math.Cos(spikeAngle) * spikeLineLength); spikeLinePoint1.Y = (float)(contourBoxMiddlePoint2.Y + Math.Sin(spikeAngle) * spikeLineLength); // Find point of impact with surface PointF?camPoi = MeasureService.FindLinesIntersection(spikeLinePoint1, spikeLinePoint2, new PointF(0, (float)cam.surfaceSlider), new PointF(cam.resolutionWidth, (float)cam.surfaceSlider)); // Translate cam surface POI to dartboard projection var frameSemiWidth = cam.resolutionWidth / 2; var camFovSemiAngle = cam.camFovAngle / 2; var projectionToCenter = new PointF(); var surfacePoiToCenterDistance = MeasureService.FindDistance(new PointF((float)cam.surfaceCenterSlider, (float)cam.surfaceSlider), camPoi.GetValueOrDefault()); var surfaceLeftToPoiDistance = MeasureService.FindDistance(new PointF((float)cam.surfaceCenterSlider - cam.resolutionWidth / 3, (float)cam.surfaceSlider), camPoi.GetValueOrDefault()); var surfaceRightToPoiDistance = MeasureService.FindDistance(new PointF((float)cam.surfaceCenterSlider + cam.resolutionWidth / 3, (float)cam.surfaceSlider), camPoi.GetValueOrDefault()); var projectionCamToCenterDistance = frameSemiWidth / Math.Sin(Math.PI * camFovSemiAngle / 180.0) * Math.Cos(Math.PI * camFovSemiAngle / 180.0); var projectionCamToPoiDistance = Math.Sqrt(Math.Pow(projectionCamToCenterDistance, 2) + Math.Pow(surfacePoiToCenterDistance, 2)); var projectionPoiToCenterDistance = Math.Sqrt(Math.Pow(projectionCamToPoiDistance, 2) - Math.Pow(projectionCamToCenterDistance, 2)); var poiCamCenterAngle = Math.Asin(projectionPoiToCenterDistance / projectionCamToPoiDistance); projectionToCenter.X = (float)(cam.camSetupPoint.X - Math.Cos(cam.toBullAngle) * projectionCamToCenterDistance); projectionToCenter.Y = (float)(cam.camSetupPoint.Y - Math.Sin(cam.toBullAngle) * projectionCamToCenterDistance); if (surfaceLeftToPoiDistance < surfaceRightToPoiDistance) { poiCamCenterAngle *= -1; } var projectionPoi = new PointF((float)(cam.camSetupPoint.X + Math.Cos(cam.toBullAngle + poiCamCenterAngle) * 2000), (float)(cam.camSetupPoint.Y + Math.Sin(cam.toBullAngle + poiCamCenterAngle) * 2000)); // Draw line from cam through projection POI var rayPoint = projectionPoi; var angle = MeasureService.FindAngle(cam.camSetupPoint, rayPoint); rayPoint.X = (float)(cam.camSetupPoint.X + Math.Cos(angle) * 2000); rayPoint.Y = (float)(cam.camSetupPoint.Y + Math.Sin(angle) * 2000); return(new Ray(cam.camNumber, cam.camSetupPoint, rayPoint, dartContour.Area)); }