private void FindAndProcessDartContour(CamService cam) { var dartContour = TryFindDartContour(cam); if (dartContour != null) { var toDartRay = ProcessDartContour(cam, dartContour); throwService.SaveRay(toDartRay); Application.Current.Dispatcher.Invoke(() => { camsDetectionBoard.DrawRay(toDartRay); }); } }
public void ProcessDartContour() { logger.Debug($"Process dartContour for cam_{camService.camNumber} start"); // 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)camService.roiPosYSlider + box[0].Y); var contourBoxPoint2 = new PointF(box[1].X, (float)camService.roiPosYSlider + box[1].Y); var contourBoxPoint3 = new PointF(box[2].X, (float)camService.roiPosYSlider + box[2].Y); var contourBoxPoint4 = new PointF(box[3].X, (float)camService.roiPosYSlider + box[3].Y); // Setup vertical contour middlepoints var contourHeight = FindDistance(contourBoxPoint1, contourBoxPoint2); var contourWidth = FindDistance(contourBoxPoint4, contourBoxPoint1); PointF contourBoxMiddlePoint1; PointF contourBoxMiddlePoint2; if (contourWidth > contourHeight) { contourBoxMiddlePoint1 = FindMiddle(contourBoxPoint1, contourBoxPoint2); contourBoxMiddlePoint2 = FindMiddle(contourBoxPoint4, contourBoxPoint3); } else { contourBoxMiddlePoint1 = FindMiddle(contourBoxPoint4, contourBoxPoint1); contourBoxMiddlePoint2 = FindMiddle(contourBoxPoint3, contourBoxPoint2); } // Find spikeLine to surface var spikeLinePoint1 = contourBoxMiddlePoint1; var spikeLinePoint2 = contourBoxMiddlePoint2; var spikeLineLength = camService.surfacePoint2.Y - contourBoxMiddlePoint2.Y; var spikeAngle = 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 = FindLinesIntersection(spikeLinePoint1, spikeLinePoint2, camService.surfacePoint1, camService.surfacePoint2); // Translate cam surface POI to dartboard projection var frameWidth = camService.RoiLastThrowFrame.Cols; var frameSemiWidth = frameWidth / 2; var camFovSemiAngle = camFovAngle / 2; var projectionToCenter = new PointF(); var surfacePoiToCenterDistance = FindDistance(camService.surfaceCenterPoint1, camPoi.GetValueOrDefault()); var surfaceLeftToPoiDistance = FindDistance(camService.surfaceLeftPoint1, camPoi.GetValueOrDefault()); var surfaceRightToPoiDistance = FindDistance(camService.surfaceRightPoint1, 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)(camService.setupPoint.X - Math.Cos(camService.toBullAngle) * projectionCamToCenterDistance); projectionToCenter.Y = (float)(camService.setupPoint.Y - Math.Sin(camService.toBullAngle) * projectionCamToCenterDistance); if (surfaceLeftToPoiDistance < surfaceRightToPoiDistance) { poiCamCenterAngle *= -1; } var projectionPoi = new PointF { X = (float)(camService.setupPoint.X + Math.Cos(camService.toBullAngle + poiCamCenterAngle) * 2000), Y = (float)(camService.setupPoint.Y + Math.Sin(camService.toBullAngle + poiCamCenterAngle) * 2000) }; // Draw line from cam through projection POI var rayPoint = projectionPoi; var angle = FindAngle(camService.setupPoint, rayPoint); rayPoint.X = (float)(camService.setupPoint.X + Math.Cos(angle) * 2000); rayPoint.Y = (float)(camService.setupPoint.Y + Math.Sin(angle) * 2000); drawService.ProjectionDrawLine(camService.setupPoint, rayPoint, new Bgr(Color.DodgerBlue).MCvScalar); var ray = new Ray(camService.camNumber, camService.setupPoint, rayPoint, dartContour.Arc); throwService.SaveRay(ray); logger.Debug($"Process dartContour for cam_{camService.camNumber} end. Ray saved:{ray}"); }