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 CamService(MainWindow mainWindow, string parentGridName, CamServiceWorkingMode mode = CamServiceWorkingMode.Work) { this.mode = mode; this.mainWindow = mainWindow; this.parentGridName = parentGridName; logger = MainWindow.ServiceContainer.Resolve <Logger>(); drawService = MainWindow.ServiceContainer.Resolve <DrawService>(); configService = MainWindow.ServiceContainer.Resolve <ConfigService>(); measureService = new MeasureService(this); var camIndex = -1; switch (parentGridName) { case "Cam1Grid": camNumber = 1; setupPoint = new PointF(configService.Read <float>(SettingsType.Cam1X), configService.Read <float>(SettingsType.Cam1Y)); camIndex = GetCamIndex(SettingsType.Cam1Id); break; case "Cam2Grid": camNumber = 2; setupPoint = new PointF(configService.Read <float>(SettingsType.Cam2X), configService.Read <float>(SettingsType.Cam2Y)); camIndex = GetCamIndex(SettingsType.Cam2Id); break; case "Cam3Grid": camNumber = 3; setupPoint = new PointF(configService.Read <float>(SettingsType.Cam3X), configService.Read <float>(SettingsType.Cam3Y)); camIndex = GetCamIndex(SettingsType.Cam3Id); break; case "Cam4Grid": camNumber = 4; setupPoint = new PointF(configService.Read <float>(SettingsType.Cam4X), configService.Read <float>(SettingsType.Cam4Y)); camIndex = GetCamIndex(SettingsType.Cam4Id); break; } resolutionWidth = configService.Read <int>(SettingsType.ResolutionWidth); resolutionHeight = configService.Read <int>(SettingsType.ResolutionHeight); movesExtraction = configService.Read <int>(SettingsType.MovesExtraction); movesDart = configService.Read <int>(SettingsType.MovesDart); movesNoise = configService.Read <int>(SettingsType.MovesNoise); smoothGauss = configService.Read <int>(SettingsType.SmoothGauss); toBullAngle = MeasureService.FindAngle(setupPoint, DrawService.projectionCenterPoint); videoCapture = new VideoCapture(camIndex, VideoCapture.API.DShow); videoCapture.SetCaptureProperty(CapProp.FrameWidth, resolutionWidth); videoCapture.SetCaptureProperty(CapProp.FrameHeight, resolutionHeight); GetSlidersData(); RefreshImageBoxes(); }
public string FindContourOnRoiFrame(CamService cam) { var allContours = new VectorOfVectorOfPoint(); CvInvoke.FindContours(cam.RoiFrame, allContours, new Mat(), RetrType.External, ChainApproxMethod.ChainApproxNone); var contour = new VectorOfPoint(); var contourArс = 0.0; var contourArea = 0.0; var contourWidth = 0.0; for (var i = 0; i < allContours.Size; i++) { var tempContour = allContours[i]; var tempContourArс = CvInvoke.ArcLength(tempContour, true); if (tempContourArс > contourArс) { contour = tempContour; contourArс = tempContourArс; } } if (contourArс > 0) { contourArea = CvInvoke.ContourArea(contour); var rect = CvInvoke.MinAreaRect(contour); 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 contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y); var side1 = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2); var side2 = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1); contourWidth = side1 < side2 ? side1 : side2; } return(Converter.ToString($"Contour\n" + $"Arc:\n" + $"{(int) contourArс}\n" + $"Area:\n" + $"{(int) contourArea}\n" + $"Width:\n" + $"{(int) contourWidth}\n" )); }
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); }
public CamService(CamNumber camNumber, ILogger logger, DrawService drawService, IConfigService configService) { this.camNumber = camNumber; this.logger = logger; this.drawService = drawService; this.configService = configService; var camIndex = -1; switch (camNumber) { case CamNumber._1: camIndex = GetCamIndexById(configService.Cam1Id); thresholdSlider = configService.Cam1ThresholdSliderValue; roiPosYSlider = configService.Cam1RoiPosYSliderValue; roiHeightSlider = configService.Cam1RoiHeightSliderValue; surfaceSlider = configService.Cam1SurfaceSliderValue; surfaceCenterSlider = configService.Cam1SurfaceCenterSliderValue; camSetupPoint = new PointF(configService.Cam1XSetupValue, configService.Cam1YSetupValue); break; case CamNumber._2: camIndex = GetCamIndexById(configService.Cam2Id); thresholdSlider = configService.Cam2ThresholdSliderValue; roiPosYSlider = configService.Cam2RoiPosYSliderValue; roiHeightSlider = configService.Cam2RoiHeightSliderValue; surfaceSlider = configService.Cam2SurfaceSliderValue; surfaceCenterSlider = configService.Cam2SurfaceCenterSliderValue; camSetupPoint = new PointF(configService.Cam2XSetupValue, configService.Cam2YSetupValue); break; case CamNumber._3: camIndex = GetCamIndexById(configService.Cam3Id); thresholdSlider = configService.Cam3ThresholdSliderValue; roiPosYSlider = configService.Cam3RoiPosYSliderValue; roiHeightSlider = configService.Cam3RoiHeightSliderValue; surfaceSlider = configService.Cam3SurfaceSliderValue; surfaceCenterSlider = configService.Cam3SurfaceCenterSliderValue; camSetupPoint = new PointF(configService.Cam3XSetupValue, configService.Cam3YSetupValue); break; case CamNumber._4: camIndex = GetCamIndexById(configService.Cam4Id); thresholdSlider = configService.Cam4ThresholdSliderValue; roiPosYSlider = configService.Cam4RoiPosYSliderValue; roiHeightSlider = configService.Cam4RoiHeightSliderValue; surfaceSlider = configService.Cam4SurfaceSliderValue; surfaceCenterSlider = configService.Cam4SurfaceCenterSliderValue; camSetupPoint = new PointF(configService.Cam4XSetupValue, configService.Cam4YSetupValue); break; default: throw new ArgumentOutOfRangeException(nameof(camNumber), camNumber, null); } resolutionWidth = configService.CamsResolutionWidth; resolutionHeight = configService.CamsResolutionHeight; smoothGauss = configService.SmoothGaussValue; camFovAngle = configService.CamsFovAngle; videoCapture = new VideoCapture(camIndex, VideoCapture.API.DShow); videoCapture.SetCaptureProperty(CapProp.FrameWidth, resolutionWidth); videoCapture.SetCaptureProperty(CapProp.FrameHeight, resolutionHeight); var projectionCenterPoint = new PointF((float)DrawService.ProjectionFrameSide / 2, (float)DrawService.ProjectionFrameSide / 2); toBullAngle = MeasureService.FindAngle(camSetupPoint, projectionCenterPoint); }
private DetectedThrow PrepareThrowData(PointF poi, Ray firstRay, Ray secondRay) { var sectors = new List <int>() { 14, 9, 12, 5, 20, 1, 18, 4, 13, 6, 10, 15, 2, 17, 3, 19, 7, 16, 8, 11 }; var projectionCenterPoint = new PointF((float)DrawService.ProjectionFrameSide / 2, (float)DrawService.ProjectionFrameSide / 2); var angle = MeasureService.FindAngle(projectionCenterPoint, poi); var distance = MeasureService.FindDistance(projectionCenterPoint, poi); var sector = 0; var type = ThrowType.Single; if (distance >= DrawService.ProjectionCoefficient * 95 && distance <= DrawService.ProjectionCoefficient * 105) { type = ThrowType.Tremble; } else if (distance >= DrawService.ProjectionCoefficient * 160 && distance <= DrawService.ProjectionCoefficient * 170) { type = ThrowType.Double; } // Find sector if (distance <= DrawService.ProjectionCoefficient * 7) { sector = 50; type = ThrowType.Bull; } else if (distance > DrawService.ProjectionCoefficient * 7 && distance <= DrawService.ProjectionCoefficient * 17) { sector = 25; type = ThrowType._25; } else if (distance > DrawService.ProjectionCoefficient * 170) { sector = 0; type = ThrowType.Zero; } else { var startRadSector = MeasureService.StartRadSector_1114; var radSector = startRadSector; foreach (var proceedSector in sectors) { if (angle >= radSector && angle < radSector + MeasureService.SectorStepRad) { sector = proceedSector; break; } sector = 11; // todo - works, but not looks pretty radSector += MeasureService.SectorStepRad; } } return(new DetectedThrow(poi, firstRay, secondRay, sector, type, DrawService.ProjectionFrameSide)); }
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)); }
private MovesDetectionResult DetectMoves(CamService cam) { var maxDartContourArc = configService.MaxContourArcValue * 1.5; var maxDartContourArea = configService.MaxContourAreaValue * 1.5; var maxDartContourWidth = configService.MaxContourWidthValue * 1.5; var minDartContourArc = configService.MinContourArcValue; var minDartContourArea = configService.MinContourAreaValue; var minDartContourWidth = configService.MinContourWidthValue; var allContours = new VectorOfVectorOfPoint(); CvInvoke.FindContours(cam.ThrowExtractedRoiFrame, allContours, new Mat(), RetrType.External, ChainApproxMethod.ChainApproxNone); if (!detectionEnabled || allContours.Size == 0) { return(MovesDetectionResult.Nothing); } var contourWithMaxArc = new VectorOfPoint(); var contourWithMaxArea = new VectorOfPoint(); var contourWithMaxWidth = new VectorOfPoint(); var maxArс = 0.0; var maxArea = 0.0; var maxWidth = 0.0; for (var i = 0; i < allContours.Size; i++) { var tempContour = allContours[i]; var tempContourArс = CvInvoke.ArcLength(tempContour, true); if (tempContourArс > maxArс) { maxArс = tempContourArс; contourWithMaxArc = tempContour; } var tempContourArea = CvInvoke.ContourArea(tempContour); if (tempContourArea > maxArea) { maxArea = tempContourArea; contourWithMaxArea = tempContour; } var rect = CvInvoke.MinAreaRect(tempContour); 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 contourBoxPoint4 = new PointF(box[3].X, (float)cam.roiPosYSlider + box[3].Y); var side1 = MeasureService.FindDistance(contourBoxPoint1, contourBoxPoint2); var side2 = MeasureService.FindDistance(contourBoxPoint4, contourBoxPoint1); var tempContourWidth = side1 < side2 ? side1 : side2; if (tempContourWidth > maxWidth) { maxWidth = tempContourWidth; contourWithMaxWidth = tempContour; } } if (workingMode == DetectionServiceWorkingMode.Crossing || maxArс >= minDartContourArc && maxArс <= maxDartContourArc && maxArea >= minDartContourArea && maxArea <= maxDartContourArea && maxWidth >= minDartContourWidth && maxWidth <= maxDartContourWidth && contourWithMaxArc.Equals(contourWithMaxArea) && contourWithMaxArea.Equals(contourWithMaxWidth) && contourWithMaxWidth.Equals(contourWithMaxArc) ) { return(MovesDetectionResult.Throw); } if (maxArс > maxDartContourArc || maxArea > maxDartContourArea || maxWidth > maxDartContourWidth) { return(MovesDetectionResult.Extraction); } return(MovesDetectionResult.Nothing); }